Title: [90877] trunk
Revision
90877
Author
[email protected]
Date
2011-07-12 18:46:09 -0700 (Tue, 12 Jul 2011)

Log Message

DFG JIT does not implement op_construct.
https://bugs.webkit.org/show_bug.cgi?id=64066

Source/_javascript_Core:

Patch by Filip Pizlo <[email protected]> on 2011-07-12
Reviewed by Gavin Barraclough.

This is a fixed implementation of op_construct.  Constructor calls are implemented
by reusing almost all of the code for Call, with care taken to make sure that
where the are differences (like selecting different code blocks), those differences
are respected.  The two fixes over the last patch are: (1) make sure the
CodeBlock::unlinkCalls respects differences between Call and Construct, and (2)
make sure that virtualFor() in DFGOperations respects the CodeSpecializationKind
(either CodeForCall or CodeForConstruct) when invoking the compiler.

* dfg/DFGAliasTracker.h:
(JSC::DFG::AliasTracker::recordConstruct):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGJITCodeGenerator.cpp:
(JSC::DFG::JITCodeGenerator::emitCall):
* dfg/DFGNode.h:
* dfg/DFGNonSpeculativeJIT.cpp:
(JSC::DFG::NonSpeculativeJIT::compile):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGRepatch.cpp:
(JSC::DFG::dfgLinkFor):
* dfg/DFGRepatch.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* runtime/CodeBlock.cpp:
(JSC::CodeBlock::unlinkCalls):

LayoutTests:

Patch by Filip Pizlo <[email protected]> on 2011-07-12
Reviewed by Gavin Barraclough.

Added a test for the DFG op_construct regression, where polymorphic constructor
calls will result in the code being compiled for call but then invoked as a
constructor.  This test will fail if that part of the patch is omitted.

* fast/js/polymorphic-construct-expected.txt: Added.
* fast/js/polymorphic-construct.html: Added.
* fast/js/script-tests/polymorphic-construct.js: Added.
(Foo):
():

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (90876 => 90877)


--- trunk/LayoutTests/ChangeLog	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/LayoutTests/ChangeLog	2011-07-13 01:46:09 UTC (rev 90877)
@@ -1,3 +1,20 @@
+2011-07-12  Filip Pizlo  <[email protected]>
+
+        DFG JIT does not implement op_construct.
+        https://bugs.webkit.org/show_bug.cgi?id=64066
+
+        Reviewed by Gavin Barraclough.
+
+        Added a test for the DFG op_construct regression, where polymorphic constructor
+        calls will result in the code being compiled for call but then invoked as a
+        constructor.  This test will fail if that part of the patch is omitted.
+
+        * fast/js/polymorphic-construct-expected.txt: Added.
+        * fast/js/polymorphic-construct.html: Added.
+        * fast/js/script-tests/polymorphic-construct.js: Added.
+        (Foo):
+        ():
+
 2011-07-12  Chris Rogers  <[email protected]>
 
         Enable Web Audio for chromium DRT

Added: trunk/LayoutTests/fast/js/polymorphic-construct-expected.txt (0 => 90877)


--- trunk/LayoutTests/fast/js/polymorphic-construct-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/polymorphic-construct-expected.txt	2011-07-13 01:46:09 UTC (rev 90877)
@@ -0,0 +1,21 @@
+This tests that polymorphic construction works correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS construct(Foo).field is 'foo'
+PASS construct(Foo).field is 'foo'
+PASS construct(Foo).field is 'foo'
+PASS construct(Foo).field is 'foo'
+PASS construct(Bar).field is 'bar'
+PASS construct(Baz).field is 'baz'
+PASS construct(Foo).field is 'foo'
+PASS construct(Bar).field is 'bar'
+PASS construct(Baz).field is 'baz'
+PASS construct(Foo).field is 'foo'
+PASS construct(Bar).field is 'bar'
+PASS construct(Baz).field is 'baz'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/polymorphic-construct.html (0 => 90877)


--- trunk/LayoutTests/fast/js/polymorphic-construct.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/polymorphic-construct.html	2011-07-13 01:46:09 UTC (rev 90877)
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href=""
+<script src=""
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/script-tests/polymorphic-construct.js (0 => 90877)


--- trunk/LayoutTests/fast/js/script-tests/polymorphic-construct.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/polymorphic-construct.js	2011-07-13 01:46:09 UTC (rev 90877)
@@ -0,0 +1,31 @@
+description(
+"This tests that polymorphic construction works correctly."
+);
+
+function Foo() {
+    this.field = "foo";
+}
+
+function Bar() {
+    this.field = "bar";
+}
+
+function Baz() {
+    this.field = "baz";
+}
+
+function construct(what) {
+    return new what();
+}
+
+for (var i = 0; i < 3; ++i) {
+    shouldBe("construct(Foo).field", "'foo'");
+}
+
+for (var i = 0; i < 3; ++i) {
+    shouldBe("construct(Foo).field", "'foo'");
+    shouldBe("construct(Bar).field", "'bar'");
+    shouldBe("construct(Baz).field", "'baz'");
+}
+
+var successfullyParsed = true;

Modified: trunk/Source/_javascript_Core/ChangeLog (90876 => 90877)


--- trunk/Source/_javascript_Core/ChangeLog	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-07-13 01:46:09 UTC (rev 90877)
@@ -1,3 +1,38 @@
+2011-07-12  Filip Pizlo  <[email protected]>
+
+        DFG JIT does not implement op_construct.
+        https://bugs.webkit.org/show_bug.cgi?id=64066
+
+        Reviewed by Gavin Barraclough.
+        
+        This is a fixed implementation of op_construct.  Constructor calls are implemented
+        by reusing almost all of the code for Call, with care taken to make sure that
+        where the are differences (like selecting different code blocks), those differences
+        are respected.  The two fixes over the last patch are: (1) make sure the
+        CodeBlock::unlinkCalls respects differences between Call and Construct, and (2)
+        make sure that virtualFor() in DFGOperations respects the CodeSpecializationKind
+        (either CodeForCall or CodeForConstruct) when invoking the compiler.
+
+        * dfg/DFGAliasTracker.h:
+        (JSC::DFG::AliasTracker::recordConstruct):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::addCall):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGJITCodeGenerator.cpp:
+        (JSC::DFG::JITCodeGenerator::emitCall):
+        * dfg/DFGNode.h:
+        * dfg/DFGNonSpeculativeJIT.cpp:
+        (JSC::DFG::NonSpeculativeJIT::compile):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::dfgLinkFor):
+        * dfg/DFGRepatch.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * runtime/CodeBlock.cpp:
+        (JSC::CodeBlock::unlinkCalls):
+
 2011-07-12  Oliver Hunt  <[email protected]>
 
         Overzealous type validation in method_check

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (90876 => 90877)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2011-07-13 01:46:09 UTC (rev 90877)
@@ -1751,7 +1751,7 @@
             continue;
         if (getJITCode().jitType() == JITCode::DFGJIT) {
 #if ENABLE(DFG_JIT)
-            repatchBuffer.relink(CodeLocationCall(m_callLinkInfos[i].callReturnLocation), operationLinkCall);
+            repatchBuffer.relink(CodeLocationCall(m_callLinkInfos[i].callReturnLocation), m_callLinkInfos[i].isCall ? operationLinkCall : operationLinkConstruct);
 #else
             ASSERT_NOT_REACHED();
 #endif

Modified: trunk/Source/_javascript_Core/dfg/DFGAliasTracker.h (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGAliasTracker.h	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGAliasTracker.h	2011-07-13 01:46:09 UTC (rev 90877)
@@ -107,6 +107,12 @@
         m_candidateAliasGetByVal = NoNode;
     }
 
+    void recordConstruct(NodeIndex construct)
+    {
+        ASSERT_UNUSED(construct, m_graph[construct].op == Construct);
+        m_candidateAliasGetByVal = NoNode;
+    }
+
 private:
     // This method returns true for arguments:
     //   - (X, X)

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-07-13 01:46:09 UTC (rev 90877)
@@ -411,6 +411,23 @@
         m_graph.m_varArgChildren.append(child);
         m_numPassedVarArgs++;
     }
+    
+    NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op)
+    {
+        addVarArgChild(get(currentInstruction[1].u.operand));
+        int argCount = currentInstruction[2].u.operand;
+        int registerOffset = currentInstruction[3].u.operand;
+        int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
+        for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++)
+            addVarArgChild(get(argIdx));
+        NodeIndex call = addToGraph(Node::VarArg, op);
+        Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
+        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
+            set(putInstruction[1].u.operand, call);
+        if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
+            m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
+        return call;
+    }
 
     void predictArray(NodeIndex nodeIndex)
     {
@@ -1101,27 +1118,18 @@
         }
             
         case op_call: {
-            addVarArgChild(get(currentInstruction[1].u.operand));
-            int argCount = currentInstruction[2].u.operand;
-            int registerOffset = currentInstruction[3].u.operand;
-            int firstArg = registerOffset - argCount - RegisterFile::CallFrameHeaderSize;
-            for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++)
-                addVarArgChild(get(argIdx));
-            NodeIndex call = addToGraph(Node::VarArg, Call);
+            NodeIndex call = addCall(interpreter, currentInstruction, Call);
             aliases.recordCall(call);
-            Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
-            if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
-                set(putInstruction[1].u.operand, call);
-            if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
-                m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
             NEXT_OPCODE(op_call);
         }
             
+        case op_construct: {
+            NodeIndex construct = addCall(interpreter, currentInstruction, Construct);
+            aliases.recordConstruct(construct);
+            NEXT_OPCODE(op_construct);
+        }
+            
         case op_call_put_result: {
-#if !ASSERT_DISABLED
-            Instruction* callInstruction = currentInstruction - OPCODE_LENGTH(op_call);
-            ASSERT(interpreter->getOpcodeID(callInstruction->u.opcode) == op_call);
-#endif
             NEXT_OPCODE(op_call_put_result);
         }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-07-13 01:46:09 UTC (rev 90877)
@@ -470,6 +470,18 @@
 
 void JITCodeGenerator::emitCall(Node& node)
 {
+    P_DFGOperation_E slowCallFunction;
+    bool isCall;
+    
+    if (node.op == Call) {
+        slowCallFunction = operationLinkCall;
+        isCall = true;
+    } else {
+        ASSERT(node.op == Construct);
+        slowCallFunction = operationLinkConstruct;
+        isCall = false;
+    }
+    
     NodeIndex calleeNodeIndex = m_jit.graph().m_varArgChildren[node.firstChild()];
     JSValueOperand callee(this, calleeNodeIndex);
     GPRReg calleeGPR = callee.gpr();
@@ -501,14 +513,7 @@
         m_jit.storePtr(argGPR, addressOfCallData(-callDataSize + argIdx));
     }
     
-    switch (node.op) {
-    case Call:
-        m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
-        break;
-        
-    default:
-        ASSERT_NOT_REACHED();
-    }
+    m_jit.storePtr(calleeGPR, addressOfCallData(RegisterFile::Callee));
     
     flushRegisters();
     
@@ -518,16 +523,9 @@
     JITCompiler::DataLabelPtr targetToCheck;
     JITCompiler::Jump slowPath;
     
-    switch (node.op) {
-    case Call:
-        slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
-        m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
-        m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
-        break;
-        
-    default:
-        ASSERT_NOT_REACHED();
-    }
+    slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
+    m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
+    m_jit.storePtr(resultGPR, addressOfCallData(RegisterFile::ScopeChain));
 
     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
     
@@ -539,7 +537,7 @@
     slowPath.link(&m_jit);
     
     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
-    JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(operationLinkCall, m_jit.graph()[m_compileIndex].exceptionInfo);
+    JITCompiler::Call slowCall = m_jit.appendCallWithFastExceptionCheck(slowCallFunction, m_jit.graph()[m_compileIndex].exceptionInfo);
     m_jit.move(Imm32(numArgs), GPRInfo::regT1);
     m_jit.addPtr(Imm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
     m_jit.notifyCall(m_jit.call(GPRInfo::returnValueGPR), m_jit.graph()[m_compileIndex].exceptionInfo);
@@ -550,7 +548,7 @@
     
     jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
     
-    m_jit.addJSCall(fastCall, slowCall, targetToCheck, true, m_jit.graph()[m_compileIndex].exceptionInfo);
+    m_jit.addJSCall(fastCall, slowCall, targetToCheck, isCall, m_jit.graph()[m_compileIndex].exceptionInfo);
 }
 
 #ifndef NDEBUG

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-07-13 01:46:09 UTC (rev 90877)
@@ -142,6 +142,7 @@
     \
     /* Calls. */\
     macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
+    macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
     \
     /* Nodes for misc operations. */\
     macro(Breakpoint, NodeMustGenerate) \

Modified: trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-07-13 01:46:09 UTC (rev 90877)
@@ -1068,6 +1068,7 @@
         break;
         
     case Call:
+    case Construct:
         emitCall(node);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-07-13 01:46:09 UTC (rev 90877)
@@ -431,97 +431,145 @@
     return JSValue::encode(exec->globalData().hostCallReturnValue);
 }
 
-static void* handleHostCall(ExecState* execCallee, JSValue callee)
+static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
 {
     ExecState* exec = execCallee->callerFrame();
     JSGlobalData* globalData = &exec->globalData();
-    CallData callData;
-    CallType callType = getCallData(callee, callData);
+    if (kind == CodeForCall) {
+        CallData callData;
+        CallType callType = getCallData(callee, callData);
     
-    ASSERT(callType != CallTypeJS);
+        ASSERT(callType != CallTypeJS);
     
-    if (callType == CallTypeHost) {
-        if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
-            globalData->exception = createStackOverflowError(exec);
-            return 0;
+        if (callType == CallTypeHost) {
+            if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
+                globalData->exception = createStackOverflowError(exec);
+                return 0;
+            }
+        
+            execCallee->setScopeChain(exec->scopeChain());
+        
+            globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
+        
+            if (globalData->exception)
+                return 0;
+            return reinterpret_cast<void*>(getHostCallReturnValue);
         }
+    
+        ASSERT(callType == CallTypeNone);
+    } else {
+        ASSERT(kind == CodeForConstruct);
         
-        execCallee->setScopeChain(exec->scopeChain());
+        ConstructData constructData;
+        ConstructType constructType = getConstructData(callee, constructData);
         
-        globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
+        ASSERT(constructType = ConstructTypeJS);
         
-        if (globalData->exception)
-            return 0;
-        return reinterpret_cast<void*>(getHostCallReturnValue);
+        if (constructType == ConstructTypeHost) {
+            if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
+                globalData->exception = createStackOverflowError(exec);
+                return 0;
+            }
+            
+            execCallee->setScopeChain(exec->scopeChain());
+            
+            globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
+            
+            if (globalData->exception)
+                return 0;
+            return reinterpret_cast<void*>(getHostCallReturnValue);
+        }
+        
+        ASSERT(constructType == ConstructTypeNone);
     }
-    
-    ASSERT(callType == CallTypeNone);
     exec->globalData().exception = createNotAFunctionError(exec, callee);
     return 0;
 }
 
-void* operationLinkCallWithReturnAddress(ExecState*, ReturnAddressPtr);
-FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkCall);
-void* operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
+inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
 {
     ExecState* exec = execCallee->callerFrame();
     JSGlobalData* globalData = &exec->globalData();
     JSValue calleeAsValue = execCallee->calleeAsValue();
     JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue);
     if (!calleeAsFunctionCell)
-        return handleHostCall(execCallee, calleeAsValue);
+        return handleHostCall(execCallee, calleeAsValue, kind);
     JSFunction* callee = asFunction(calleeAsFunctionCell);
     ExecutableBase* executable = callee->executable();
     
     MacroAssemblerCodePtr codePtr;
     CodeBlock* codeBlock = 0;
     if (executable->isHostFunction())
-        codePtr = executable->generatedJITCodeForCall().addressForCall();
+        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
     else {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
-        JSObject* error = functionExecutable->compileForCall(exec, callee->scope());
+        JSObject* error = functionExecutable->compileFor(exec, callee->scope(), kind);
         if (error) {
             globalData->exception = createStackOverflowError(exec);
             return 0;
         }
-        codeBlock = &functionExecutable->generatedBytecodeForCall();
+        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
         if (execCallee->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
-            codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
+            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
         else
-            codePtr = functionExecutable->generatedJITCodeForCallWithArityCheck();
+            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
         execCallee->setScopeChain(callee->scope());
     }
     CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
     if (!callLinkInfo.seenOnce())
         callLinkInfo.setSeen();
     else
-        dfgLinkCall(execCallee, callLinkInfo, codeBlock, callee, codePtr);
+        dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
     return codePtr.executableAddress();
 }
 
-void* operationVirtualCall(ExecState* execCallee)
+void* operationLinkCallWithReturnAddress(ExecState*, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkCall);
+void* operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
 {
+    return linkFor(execCallee, returnAddress, CodeForCall);
+}
+
+void* operationLinkConstructWithReturnAddress(ExecState*, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkConstruct);
+void* operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
+{
+    return linkFor(execCallee, returnAddress, CodeForConstruct);
+}
+
+inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
+{
     ExecState* exec = execCallee->callerFrame();
     JSGlobalData* globalData = &exec->globalData();
     JSValue calleeAsValue = execCallee->calleeAsValue();
     JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue);
     if (UNLIKELY(!calleeAsFunctionCell))
-        return handleHostCall(execCallee, calleeAsValue);
+        return handleHostCall(execCallee, calleeAsValue, kind);
     
     JSFunction* function = asFunction(calleeAsFunctionCell);
     ExecutableBase* executable = function->executable();
-    if (UNLIKELY(!executable->hasJITCodeForCall())) {
+    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
-        JSObject* error = functionExecutable->compileForCall(exec, function->scope());
+        JSObject* error = functionExecutable->compileFor(exec, function->scope(), kind);
         if (error) {
             exec->globalData().exception = error;
             return 0;
         }
     }
     execCallee->setScopeChain(function->scopeUnchecked());
-    return executable->generatedJITCodeForCallWithArityCheck().executableAddress();
+    return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
 }
 
+void* operationVirtualCall(ExecState* execCallee)
+{
+    return virtualFor(execCallee, CodeForCall);
+}
+
+void* operationVirtualConstruct(ExecState* execCallee)
+{
+    return virtualFor(execCallee, CodeForConstruct);
+}
+
 EncodedJSValue operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, EncodedJSValue encodedPrototype)
 {
     JSValue value = JSValue::decode(encodedValue);

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-07-13 01:46:09 UTC (rev 90877)
@@ -48,6 +48,7 @@
 typedef void (*V_DFGOperation_EJJP)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
 typedef void (*V_DFGOperation_EJJI)(ExecState*, EncodedJSValue, EncodedJSValue, Identifier*);
 typedef double (*D_DFGOperation_DD)(double, double);
+typedef void *(*P_DFGOperation_E)(ExecState*);
 
 // These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
 EncodedJSValue operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
@@ -83,6 +84,8 @@
 bool operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 void* operationVirtualCall(ExecState*);
 void* operationLinkCall(ExecState*);
+void* operationVirtualConstruct(ExecState*);
+void* operationLinkConstruct(ExecState*);
 
 // This method is used to lookup an exception hander, keyed by faultLocation, which is
 // the return location from one of the calls out to one of the helper operations above.

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-07-13 01:46:09 UTC (rev 90877)
@@ -434,7 +434,7 @@
         dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriatePutByIdFunction(slot, putKind));
 }
 
-void dfgLinkCall(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr)
+void dfgLinkFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind)
 {
     CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
     
@@ -446,7 +446,12 @@
         repatchBuffer.relink(callLinkInfo.hotPathOther, codePtr);
     }
     
-    repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall);
+    if (kind == CodeForCall) {
+        repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall);
+        return;
+    }
+    ASSERT(kind == CodeForConstruct);
+    repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualConstruct);
 }
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.h (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.h	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.h	2011-07-13 01:46:09 UTC (rev 90877)
@@ -37,7 +37,7 @@
 void dfgRepatchGetMethod(ExecState*, JSValue, const Identifier&, const PropertySlot&, MethodCallLinkInfo&);
 void dfgBuildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
 void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
-void dfgLinkCall(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr);
+void dfgLinkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind);
 
 } } // namespace JSC::DFG
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (90876 => 90877)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-07-13 01:33:50 UTC (rev 90876)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-07-13 01:46:09 UTC (rev 90877)
@@ -1143,6 +1143,7 @@
         break;
         
     case Call:
+    case Construct:
         emitCall(node);
         break;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to