Commit 9e1c8098 authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: DFG should have switch_char

https://bugs.webkit.org/show_bug.cgi?id=117710

Source/JavaScriptCore:

Reviewed by Michael Saboff.

Add op_switch_char. Most of this is fairly simple, except for the whole
LazyJSValue thing.

It's long been the case that anytime you wanted the DFG to speak of a string
that didn't appear in the constant pool, you would have a hard time since
the DFG isn't allowed to allocate in the GC heap. For example, if you know
that you want to speak of a single character string, you might find that
the one you wanted to speak of had been GC'd. Another example is if you
wanted to add constant folding for string concatenation - something we don't
have yet but will want eventually.

I solve this by finally adding the notion of LazyJSValue. In the future I
anticipate using this for a variety of string-related things. The idea here
is that the DFG can either say that it already knows what the value is, or
it can describe the value. For example, in this patch I needed to be able to
describe single-character strings.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
* bytecode/JumpTable.h:
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(InlineStackEntry):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGCFGSimplificationPhase.cpp:
(JSC::DFG::CFGSimplificationPhase::run):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGPRInfo.h:
(JSC::DFG::JSValueRegs::payloadGPR):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::jumpTable):
(DFG):
(JSC::DFG::JITCompiler::numberOfJumpTables):
(JSC::DFG::JITCompiler::linkSwitches):
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITCompiler.h:
(JITCompiler):
* dfg/DFGLazyJSValue.cpp: Added.
(DFG):
(JSC::DFG::LazyJSValue::getValue):
(JSC::DFG::equalToSingleCharacter):
(JSC::DFG::LazyJSValue::strictEqual):
(JSC::DFG::LazyJSValue::dump):
* dfg/DFGLazyJSValue.h: Added.
(DFG):
(LazyJSValue):
(JSC::DFG::LazyJSValue::LazyJSValue):
(JSC::DFG::LazyJSValue::singleCharacterString):
(JSC::DFG::LazyJSValue::tryGetValue):
(JSC::DFG::LazyJSValue::value):
(JSC::DFG::LazyJSValue::character):
(JSC::DFG::LazyJSValue::switchLookupValue):
* dfg/DFGNode.h:
(JSC::DFG::SwitchCase::SwitchCase):
(SwitchCase):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitSwitchIntJump):
(JSC::DFG::SpeculativeJIT::emitSwitchImmIntJump):
(DFG):
(JSC::DFG::SpeculativeJIT::emitSwitchImm):
(JSC::DFG::SpeculativeJIT::emitSwitchCharStringJump):
(JSC::DFG::SpeculativeJIT::emitSwitchChar):
(JSC::DFG::SpeculativeJIT::emitSwitch):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):

Source/WTF:

Reviewed by Michael Saboff.

I wanted to be able to say stringImpl->at(index), and now I can!

Also made it possible to convert a UChar to a utf8 CString without
allocating a StringImpl.

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::utf8Impl):
(WTF):
(WTF::StringImpl::utf8ForCharacters):
(WTF::StringImpl::utf8ForRange):
* wtf/text/StringImpl.h:
(StringImpl):
(WTF::StringImpl::at):
(WTF::StringImpl::operator[]):

LayoutTests:

Rubber stamped by Mark Hahnenberg.

* fast/js/regress/script-tests/switch-char-constant.js: Added.
(foo):
(bar):
* fast/js/regress/script-tests/switch-char.js: Added.
(foo):
(bar):
* fast/js/regress/switch-char-constant-expected.txt: Added.
* fast/js/regress/switch-char-constant.html: Added.
* fast/js/regress/switch-char-expected.txt: Added.
* fast/js/regress/switch-char.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153234 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 5109edb6
2013-06-18 Filip Pizlo <fpizlo@apple.com>
fourthTier: DFG should have switch_char
https://bugs.webkit.org/show_bug.cgi?id=117710
Rubber stamped by Mark Hahnenberg.
* fast/js/regress/script-tests/switch-char-constant.js: Added.
(foo):
(bar):
* fast/js/regress/script-tests/switch-char.js: Added.
(foo):
(bar):
* fast/js/regress/switch-char-constant-expected.txt: Added.
* fast/js/regress/switch-char-constant.html: Added.
* fast/js/regress/switch-char-expected.txt: Added.
* fast/js/regress/switch-char.html: Added.
2013-06-15 Filip Pizlo <fpizlo@apple.com>
fourthTier: Add CFG simplification for Switch
function foo(char) {
switch (char) {
case "a":
return 1;
case "b":
return 2;
case "c":
return 3;
default:
return 4;
}
}
function bar() {
var result = 0;
for (var i = 0; i < 1000000; ++i)
result += foo("a");
return result;
}
var result = bar();
if (result != 1000000)
throw "Error: bad result: " + result;
function foo(char) {
switch (char) {
case "a":
return 1;
case "b":
return 2;
case "c":
return 3;
default:
return 4;
}
}
function bar(array) {
var result = 0;
for (var i = 0; i < 1000000; ++i)
result += foo(array[i & 3]);
return result;
}
var result = bar(["a", "b", "c", "d"]);
if (result != 2500000)
throw "Error: bad result: " + result;
JSRegress/switch-char-constant
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/switch-char-constant.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
JSRegress/switch-char
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/switch-char.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
2013-06-18 Filip Pizlo <fpizlo@apple.com>
fourthTier: DFG should have switch_char
https://bugs.webkit.org/show_bug.cgi?id=117710
Reviewed by Michael Saboff.
Add op_switch_char. Most of this is fairly simple, except for the whole
LazyJSValue thing.
It's long been the case that anytime you wanted the DFG to speak of a string
that didn't appear in the constant pool, you would have a hard time since
the DFG isn't allowed to allocate in the GC heap. For example, if you know
that you want to speak of a single character string, you might find that
the one you wanted to speak of had been GC'd. Another example is if you
wanted to add constant folding for string concatenation - something we don't
have yet but will want eventually.
I solve this by finally adding the notion of LazyJSValue. In the future I
anticipate using this for a variety of string-related things. The idea here
is that the DFG can either say that it already knows what the value is, or
it can describe the value. For example, in this patch I needed to be able to
describe single-character strings.
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
* bytecode/JumpTable.h:
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(InlineStackEntry):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
* dfg/DFGCFGSimplificationPhase.cpp:
(JSC::DFG::CFGSimplificationPhase::run):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGPRInfo.h:
(JSC::DFG::JSValueRegs::payloadGPR):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::jumpTable):
(DFG):
(JSC::DFG::JITCompiler::numberOfJumpTables):
(JSC::DFG::JITCompiler::linkSwitches):
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITCompiler.h:
(JITCompiler):
* dfg/DFGLazyJSValue.cpp: Added.
(DFG):
(JSC::DFG::LazyJSValue::getValue):
(JSC::DFG::equalToSingleCharacter):
(JSC::DFG::LazyJSValue::strictEqual):
(JSC::DFG::LazyJSValue::dump):
* dfg/DFGLazyJSValue.h: Added.
(DFG):
(LazyJSValue):
(JSC::DFG::LazyJSValue::LazyJSValue):
(JSC::DFG::LazyJSValue::singleCharacterString):
(JSC::DFG::LazyJSValue::tryGetValue):
(JSC::DFG::LazyJSValue::value):
(JSC::DFG::LazyJSValue::character):
(JSC::DFG::LazyJSValue::switchLookupValue):
* dfg/DFGNode.h:
(JSC::DFG::SwitchCase::SwitchCase):
(SwitchCase):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::emitSwitchIntJump):
(JSC::DFG::SpeculativeJIT::emitSwitchImmIntJump):
(DFG):
(JSC::DFG::SpeculativeJIT::emitSwitchImm):
(JSC::DFG::SpeculativeJIT::emitSwitchCharStringJump):
(JSC::DFG::SpeculativeJIT::emitSwitchChar):
(JSC::DFG::SpeculativeJIT::emitSwitch):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
2013-06-19 Mark Hahnenberg <mhahnenberg@apple.com>
Refactor ObjCCallbackFunction to inherit directly from InternalFunction
......
......@@ -756,6 +756,8 @@
A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386551118697B400540279 /* SpecializedThunkJIT.h */; };
A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7386552118697B400540279 /* ThunkGenerators.cpp */; };
A7386556118697B400540279 /* ThunkGenerators.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386553118697B400540279 /* ThunkGenerators.h */; settings = {ATTRIBUTES = (Private, ); }; };
A73A535A1799CD5D00170C19 /* DFGLazyJSValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73A53581799CD5D00170C19 /* DFGLazyJSValue.cpp */; };
A73A535B1799CD5D00170C19 /* DFGLazyJSValue.h in Headers */ = {isa = PBXBuildFile; fileRef = A73A53591799CD5D00170C19 /* DFGLazyJSValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
A73E1330179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73E132C179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp */; };
A73E1331179624CD00E4DEA8 /* DFGDesiredStructureChains.h in Headers */ = {isa = PBXBuildFile; fileRef = A73E132D179624CD00E4DEA8 /* DFGDesiredStructureChains.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1789,6 +1791,8 @@
A7386551118697B400540279 /* SpecializedThunkJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecializedThunkJIT.h; sourceTree = "<group>"; };
A7386552118697B400540279 /* ThunkGenerators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThunkGenerators.cpp; sourceTree = "<group>"; };
A7386553118697B400540279 /* ThunkGenerators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThunkGenerators.h; sourceTree = "<group>"; };
A73A53581799CD5D00170C19 /* DFGLazyJSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLazyJSValue.cpp; path = dfg/DFGLazyJSValue.cpp; sourceTree = "<group>"; };
A73A53591799CD5D00170C19 /* DFGLazyJSValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLazyJSValue.h; path = dfg/DFGLazyJSValue.h; sourceTree = "<group>"; };
A73E132C179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredStructureChains.cpp; path = dfg/DFGDesiredStructureChains.cpp; sourceTree = "<group>"; };
A73E132D179624CD00E4DEA8 /* DFGDesiredStructureChains.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredStructureChains.h; path = dfg/DFGDesiredStructureChains.h; sourceTree = "<group>"; };
A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefPrivate.h; sourceTree = "<group>"; };
......@@ -2972,6 +2976,8 @@
86EC9DB31328DF44002B2AD7 /* dfg */ = {
isa = PBXGroup;
children = (
A73A53581799CD5D00170C19 /* DFGLazyJSValue.cpp */,
A73A53591799CD5D00170C19 /* DFGLazyJSValue.h */,
0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */,
0F62016E143FCD2F0068B77C /* DFGAbstractState.h */,
0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */,
......@@ -3714,6 +3720,7 @@
14CA958D16AB50FA00938A06 /* ObjectAllocationProfile.h in Headers */,
BC18C4450E16F5CD00B34460 /* ObjectConstructor.h in Headers */,
BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */,
A73A535B1799CD5D00170C19 /* DFGLazyJSValue.h in Headers */,
E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */,
969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */,
0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */,
......@@ -4283,6 +4290,7 @@
0FC09776146943B000CF2442 /* DFGOSRExitCompiler32_64.cpp in Sources */,
0FC0977214693AF900CF2442 /* DFGOSRExitCompiler64.cpp in Sources */,
0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */,
A73A535A1799CD5D00170C19 /* DFGLazyJSValue.cpp in Sources */,
0FEFC9AA1681A3B300567F53 /* DFGOSRExitJumpPlaceholder.cpp in Sources */,
0F235BED17178E7300690C7F /* DFGOSRExitPreparation.cpp in Sources */,
0FFFC95B14EF90AD00C72532 /* DFGPhase.cpp in Sources */,
......
......@@ -564,7 +564,7 @@ void CodeBlock::dumpBytecode(PrintStream& out)
continue;
ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
out.printf("\t\t\"%s\" => %04d\n", String(&ch, 1).utf8().data(), *iter);
out.printf("\t\t\"%s\" => %04d\n", StringImpl::utf8ForCharacters(&ch, 1).data(), *iter);
}
out.printf(" }\n");
++i;
......@@ -1839,6 +1839,20 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
optimizeAfterWarmUp();
jitAfterWarmUp();
// If the concurrent thread will want the code block's hash, then compute it here
// synchronously.
if (Options::showDisassembly()
|| Options::showDFGDisassembly()
|| Options::dumpBytecodeAtDFGTime()
|| Options::verboseCompilation()
|| Options::logCompilationChanges()
|| Options::validateGraph()
|| Options::validateGraphAtEachPhase()
|| Options::verboseOSR()
|| Options::verboseCompilationQueue()
|| Options::reportCompileTimes())
hash();
if (Options::dumpGeneratedBytecodes())
dumpBytecode();
m_vm->finishedCompiling(this);
......
/*
* Copyright (C) 2008 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
......
......@@ -350,14 +350,17 @@ private:
case Switch: {
SwitchData* data = node->switchData();
switch (data->kind) {
case SwitchImm: {
case SwitchImm:
case SwitchChar: {
// We don't need NodeNeedsNegZero because if the cases are all integers
// then -0 and 0 are treated the same. We don't need NodeUsedAsOther
// because if all of the cases are integers then NaN and undefined are
// treated the same.
// or strings then -0 and 0 are treated the same. We don't need
// NodeUsedAsOther because if all of the cases are integers or
// single-character strings then NaN and undefined are treated the same
// (i.e. they will take default).
node->child1()->mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
break;
} }
}
}
break;
}
......
......@@ -1010,6 +1010,7 @@ private:
Vector<unsigned> m_constantRemap;
Vector<unsigned> m_constantBufferRemap;
Vector<unsigned> m_switchImmRemap;
Vector<unsigned> m_switchCharRemap;
// Blocks introduced by this code block, which need successor linking.
// May include up to one basic block that includes the continuation after
......@@ -2776,6 +2777,26 @@ bool ByteCodeParser::parseBlock(unsigned limit)
addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(currentInstruction[3].u.operand));
LAST_OPCODE(op_switch_imm);
}
case op_switch_char: {
SwitchData data;
data.kind = SwitchChar;
data.switchTableIndex = m_inlineStackTop->m_switchCharRemap[currentInstruction[1].u.operand];
data.fallThrough = m_currentIndex + currentInstruction[2].u.operand;
SimpleJumpTable& table = m_codeBlock->characterSwitchJumpTable(data.switchTableIndex);
for (unsigned i = 0; i < table.branchOffsets.size(); ++i) {
if (!table.branchOffsets[i])
continue;
unsigned target = m_currentIndex + table.branchOffsets[i];
if (target == data.fallThrough)
continue;
data.cases.append(
SwitchCase(LazyJSValue::singleCharacterString(table.min + i), target));
}
m_graph.m_switchData.append(data);
addToGraph(Switch, OpInfo(&m_graph.m_switchData.last()), get(currentInstruction[3].u.operand));
LAST_OPCODE(op_switch_char);
}
case op_ret:
flushArgumentsAndCapturedVariables();
......@@ -3274,6 +3295,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers());
m_switchImmRemap.resize(codeBlock->numberOfImmediateSwitchJumpTables());
m_switchCharRemap.resize(codeBlock->numberOfCharacterSwitchJumpTables());
for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) {
StringImpl* rep = codeBlock->identifier(i).impl();
......@@ -3318,6 +3340,10 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
m_switchImmRemap[i] = byteCodeParser->m_codeBlock->numberOfImmediateSwitchJumpTables();
byteCodeParser->m_codeBlock->addImmediateSwitchJumpTable() = codeBlock->immediateSwitchJumpTable(i);
}
for (unsigned i = 0; i < codeBlock->numberOfCharacterSwitchJumpTables(); ++i) {
m_switchCharRemap[i] = byteCodeParser->m_codeBlock->numberOfCharacterSwitchJumpTables();
byteCodeParser->m_codeBlock->addCharacterSwitchJumpTable() = codeBlock->characterSwitchJumpTable(i);
}
m_callsiteBlockHeadNeedsLinking = true;
} else {
// Machine code block case.
......@@ -3333,6 +3359,7 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers());
m_switchImmRemap.resize(codeBlock->numberOfImmediateSwitchJumpTables());
m_switchCharRemap.resize(codeBlock->numberOfCharacterSwitchJumpTables());
for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i)
m_identifierRemap[i] = i;
for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i)
......@@ -3341,6 +3368,8 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
m_constantBufferRemap[i] = i;
for (size_t i = 0; i < codeBlock->numberOfImmediateSwitchJumpTables(); ++i)
m_switchImmRemap[i] = i;
for (size_t i = 0; i < codeBlock->numberOfCharacterSwitchJumpTables(); ++i)
m_switchCharRemap[i] = i;
m_callsiteBlockHeadNeedsLinking = false;
}
......
......@@ -188,7 +188,7 @@ public:
TriState found = FalseTriState;
BlockIndex targetBlockIndex = NoBlock;
for (unsigned i = data->cases.size(); found == FalseTriState && i--;) {
found = JSValue::pureStrictEqual(value, data->cases[i].value);
found = data->cases[i].value.strictEqual(value);
if (found == TrueTriState)
targetBlockIndex = data->cases[i].target;
}
......
......@@ -167,6 +167,7 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc
case op_typeof:
case op_to_number:
case op_switch_imm:
case op_switch_char:
case op_in:
case op_get_from_scope:
case op_put_to_scope:
......
......@@ -71,20 +71,6 @@ static CompilationResult compile(CompileMode compileMode, ExecState* exec, CodeB
return CompilationFailed;
// If the concurrent thread will want the code block's hash, then compute it here
// synchronously.
if (Options::showDisassembly()
|| Options::showDFGDisassembly()
|| Options::dumpBytecodeAtDFGTime()
|| Options::verboseCompilation()
|| Options::logCompilationChanges()
|| Options::validateGraph()
|| Options::validateGraphAtEachPhase()
|| Options::verboseOSR()
|| Options::verboseCompilationQueue()
|| Options::reportCompileTimes())
codeBlock->hash();
if (logCompilationChanges())
dataLog("DFG(Driver) compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
......
......@@ -585,6 +585,10 @@ private:
if (node->child1()->shouldSpeculateInteger())
setUseKindAndUnboxIfProfitable<Int32Use>(node->child1());
break;
case SwitchChar:
if (node->child1()->shouldSpeculateString())
setUseKindAndUnboxIfProfitable<StringUse>(node->child1());
break;
}
break;
}
......
......@@ -59,6 +59,7 @@ public:
bool operator!() const { return m_gpr == InvalidGPRReg; }
GPRReg gpr() const { return m_gpr; }
GPRReg payloadGPR() const { return m_gpr; }
private:
GPRReg m_gpr;
......
......@@ -150,40 +150,66 @@ void JITCompiler::compileExceptionHandlers()
}
}
void JITCompiler::link(LinkBuffer& linkBuffer)
SimpleJumpTable& JITCompiler::jumpTable(SwitchKind kind, unsigned index)
{
switch (kind) {
case SwitchImm:
return m_codeBlock->immediateSwitchJumpTable(index);
case SwitchChar:
return m_codeBlock->characterSwitchJumpTable(index);
}
}
unsigned JITCompiler::numberOfJumpTables(SwitchKind kind)
{
switch (kind) {
case SwitchImm:
return m_codeBlock->numberOfImmediateSwitchJumpTables();
case SwitchChar:
return m_codeBlock->numberOfCharacterSwitchJumpTables();
}
}
void JITCompiler::linkSwitches(LinkBuffer& linkBuffer, SwitchKind kind)
{
// Link the code, populate data in CodeBlock data structures.
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLogF("JIT code for %p start at [%p, %p). Size = %zu.\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize(), linkBuffer.debugSize());
#endif
BitVector usedJumpTables;
for (unsigned i = m_graph.m_switchData.size(); i--;) {
SwitchData& data = m_graph.m_switchData[i];
if (!data.didUseJumpTable)
continue;
// Cast to int to avoid tautological comparison warnings.
RELEASE_ASSERT(static_cast<int>(data.kind) == static_cast<int>(SwitchImm));
if (data.kind != kind)
continue;
usedJumpTables.set(data.switchTableIndex);
SimpleJumpTable& table =
m_codeBlock->immediateSwitchJumpTable(data.switchTableIndex);
SimpleJumpTable& table = jumpTable(kind, data.switchTableIndex);
table.ctiDefault = linkBuffer.locationOf(m_blockHeads[data.fallThrough]);
for (unsigned j = table.ctiOffsets.size(); j--;)
table.ctiOffsets[j] = table.ctiDefault;
for (unsigned j = data.cases.size(); j--;) {
SwitchCase& myCase = data.cases[j];
table.ctiOffsets[myCase.value.asInt32() - table.min] =
table.ctiOffsets[myCase.value.switchLookupValue() - table.min] =
linkBuffer.locationOf(m_blockHeads[myCase.target]);
}
}
for (unsigned i = m_codeBlock->numberOfImmediateSwitchJumpTables(); i--;) {
for (unsigned i = numberOfJumpTables(kind); i--;) {
if (usedJumpTables.get(i))
continue;
m_codeBlock->immediateSwitchJumpTable(i).clear();
jumpTable(kind, i).clear();
}
}
void JITCompiler::link(LinkBuffer& linkBuffer)
{
// Link the code, populate data in CodeBlock data structures.
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLogF("JIT code for %p start at [%p, %p). Size = %zu.\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize(), linkBuffer.debugSize());
#endif
linkSwitches(linkBuffer, SwitchImm);
linkSwitches(linkBuffer, SwitchChar);
// Link all calls out from the JIT code to their respective functions.
for (unsigned i = 0; i < m_calls.size(); ++i)
......
......@@ -472,6 +472,10 @@ private:
void compileEntry();
void compileBody();
void link(LinkBuffer&);
SimpleJumpTable& jumpTable(SwitchKind, unsigned);
unsigned numberOfJumpTables(SwitchKind);
void linkSwitches(LinkBuffer&, SwitchKind);
void exitSpeculativeWithOSR(const OSRExit&, SpeculationRecovery*);
void compileExceptionHandlers();
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DFGLazyJSValue.h"
#if ENABLE(DFG_JIT)
#include "Operations.h"
namespace JSC { namespace DFG {
JSValue LazyJSValue::getValue(VM& vm) const
{
switch (m_kind) {
case KnownValue:
return value();
case SingleCharacterString:
return jsSingleCharacterString(&vm, u.character);
}
RELEASE_ASSERT_NOT_REACHED();
}
static TriState equalToSingleCharacter(JSValue value, UChar character)
{
if (!value.isString())
return FalseTriState;
JSString* jsString = asString(value);
if (jsString->length() != 1)
return FalseTriState;
const StringImpl* string = jsString->tryGetValueImpl();
if (!string)
return MixedTriState;
return triState(string->at(0) == character);
}
TriState LazyJSValue::strictEqual(const LazyJSValue& other) const
{
switch (m_kind) {
case KnownValue:
switch (other.m_kind) {
case KnownValue:
return JSValue::pureStrictEqual(value(), other.value());
case SingleCharacterString:
return equalToSingleCharacter(value(), other.character());
}
break;
case SingleCharacterString:
switch (other.m_kind) {
case SingleCharacterString:
return triState(character() == other.character());
default:
return other.strictEqual(*this);
}
break;
}
RELEASE_ASSERT_NOT_REACHED();
}
void LazyJSValue::dump(PrintStream& out) const
{
switch (m_kind) {
case KnownValue:
value().dump(out);
return;
case SingleCharacterString:
out.print("Lazy:SingleCharacterString(");
out.printf("%04X", static_cast<unsigned>(character()));
out.print(" / ", StringImpl::utf8ForCharacters(&u.character, 1), ")");
return;
}
RELEASE_ASSERT_NOT_REACHED();
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met: