Index: src/ia32/builtins-ia32.cc |
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc |
index d56c02de19c05460d462dac8e79df250a9ab23b2..2c5b1d1f58831c6c5530172d39bc757cb64cc866 100644 |
--- a/src/ia32/builtins-ia32.cc |
+++ b/src/ia32/builtins-ia32.cc |
@@ -36,15 +36,36 @@ namespace internal { |
#define __ ACCESS_MASM(masm) |
-void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) { |
- // TODO(428): Don't pass the function in a static variable. |
- ExternalReference passed = ExternalReference::builtin_passed_function(); |
- __ mov(Operand::StaticVariable(passed), edi); |
- |
- // The actual argument count has already been loaded into register |
- // eax, but JumpToRuntime expects eax to contain the number of |
- // arguments including the receiver. |
- __ inc(eax); |
+void Builtins::Generate_Adaptor(MacroAssembler* masm, |
+ CFunctionId id, |
+ BuiltinExtraArguments extra_args) { |
+ // ----------- S t a t e ------------- |
+ // -- eax : number of arguments excluding receiver |
+ // -- edi : called function (only guaranteed when |
+ // extra_args requires it) |
+ // -- esi : context |
+ // -- esp[0] : return address |
+ // -- esp[4] : last argument |
+ // -- ... |
+ // -- esp[4 * argc] : first argument (argc == eax) |
+ // -- esp[4 * (argc +1)] : receiver |
+ // ----------------------------------- |
+ |
+ // Insert extra arguments. |
+ int num_extra_args = 0; |
+ if (extra_args == NEEDS_CALLED_FUNCTION) { |
+ num_extra_args = 1; |
+ Register scratch = ebx; |
+ __ pop(scratch); // Save return address. |
+ __ push(edi); |
+ __ push(scratch); // Restore return address. |
+ } else { |
+ ASSERT(extra_args == NO_EXTRA_ARGUMENTS); |
+ } |
+ |
+ // JumpToRuntime expects eax to contain the number of arguments |
+ // including the receiver and the extra arguments. |
+ __ add(Operand(eax), Immediate(num_extra_args + 1)); |
__ JumpToRuntime(ExternalReference(id)); |
} |
@@ -81,7 +102,8 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { |
} |
-void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
+static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
+ bool is_api_function) { |
// Enter a construct frame. |
__ EnterConstructFrame(); |
@@ -277,8 +299,17 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
__ j(greater_equal, &loop); |
// Call the function. |
- ParameterCount actual(eax); |
- __ InvokeFunction(edi, actual, CALL_FUNCTION); |
+ if (is_api_function) { |
+ __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
+ Handle<Code> code = Handle<Code>( |
+ Builtins::builtin(Builtins::HandleApiCallConstruct)); |
+ ParameterCount expected(0); |
+ __ InvokeCode(code, expected, expected, |
+ RelocInfo::CODE_TARGET, CALL_FUNCTION); |
+ } else { |
+ ParameterCount actual(eax); |
+ __ InvokeFunction(edi, actual, CALL_FUNCTION); |
+ } |
// Restore context from the frame. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
@@ -319,6 +350,16 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
} |
+void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
+ Generate_JSConstructStubHelper(masm, false); |
+} |
+ |
+ |
+void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
+ Generate_JSConstructStubHelper(masm, true); |
+} |
+ |
+ |
static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
bool is_construct) { |
// Clear the context before we push it when entering the JS frame. |