Index: src/ia32/macro-assembler-ia32.cc |
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc |
index cdcb24246a75e848a59a07b55cea356b28fd4271..4f7a65a425c138cd8bdc950fc6c704edbf3034af 100644 |
--- a/src/ia32/macro-assembler-ia32.cc |
+++ b/src/ia32/macro-assembler-ia32.cc |
@@ -1987,18 +1987,63 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
} |
-void MacroAssembler::InvokeCode(const Operand& code, |
- Register new_target, |
- const ParameterCount& expected, |
- const ParameterCount& actual, |
- InvokeFlag flag, |
- const CallWrapper& call_wrapper) { |
+void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, |
+ const ParameterCount& expected, |
+ const ParameterCount& actual) { |
+ Label skip_flooding; |
+ ExternalReference debug_step_action = |
+ ExternalReference::debug_last_step_action_address(isolate()); |
+ cmpb(Operand::StaticVariable(debug_step_action), StepIn); |
+ j(not_equal, &skip_flooding); |
+ { |
+ FrameScope frame(this, |
+ has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); |
+ if (expected.is_reg()) { |
+ SmiTag(expected.reg()); |
+ Push(expected.reg()); |
+ } |
+ if (actual.is_reg()) { |
+ SmiTag(actual.reg()); |
+ Push(actual.reg()); |
+ } |
+ if (new_target.is_valid()) { |
+ Push(new_target); |
+ } |
+ Push(fun); |
+ Push(fun); |
+ CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1); |
+ Pop(fun); |
+ if (new_target.is_valid()) { |
+ Pop(new_target); |
+ } |
+ if (actual.is_reg()) { |
+ Pop(actual.reg()); |
+ SmiUntag(actual.reg()); |
+ } |
+ if (expected.is_reg()) { |
+ Pop(expected.reg()); |
+ SmiUntag(expected.reg()); |
+ } |
+ } |
+ bind(&skip_flooding); |
+} |
+ |
+ |
+void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, |
+ const ParameterCount& expected, |
+ const ParameterCount& actual, |
+ InvokeFlag flag, |
+ const CallWrapper& call_wrapper) { |
// You can't call a function without a valid frame. |
DCHECK(flag == JUMP_FUNCTION || has_frame()); |
- |
- // Ensure new target is passed in the correct register. Otherwise clear the |
- // appropriate register in case new target is not given. |
+ DCHECK(function.is(edi)); |
DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx)); |
+ |
+ if (call_wrapper.NeedsDebugStepCheck()) { |
+ FloodFunctionIfStepping(function, new_target, expected, actual); |
+ } |
+ |
+ // Clear the new.target register if not given. |
if (!new_target.is_valid()) { |
mov(edx, isolate()->factory()->undefined_value()); |
} |
@@ -2008,6 +2053,10 @@ void MacroAssembler::InvokeCode(const Operand& code, |
InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, |
Label::kNear, call_wrapper); |
if (!definitely_mismatches) { |
+ // We call indirectly through the code field in the function to |
+ // allow recompilation to take effect without changing any of the |
+ // call sites. |
+ Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset); |
if (flag == CALL_FUNCTION) { |
call_wrapper.BeforeCall(CallSize(code)); |
call(code); |
@@ -2036,8 +2085,7 @@ void MacroAssembler::InvokeFunction(Register fun, |
SmiUntag(ebx); |
ParameterCount expected(ebx); |
- InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), new_target, |
- expected, actual, flag, call_wrapper); |
+ InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper); |
} |
@@ -2052,8 +2100,7 @@ void MacroAssembler::InvokeFunction(Register fun, |
DCHECK(fun.is(edi)); |
mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
- InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), no_reg, |
- expected, actual, flag, call_wrapper); |
+ InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper); |
} |
@@ -2077,8 +2124,7 @@ void MacroAssembler::InvokeBuiltin(int native_context_index, InvokeFlag flag, |
// parameter count to avoid emitting code to do the check. |
ParameterCount expected(0); |
GetBuiltinFunction(edi, native_context_index); |
- InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), no_reg, |
- expected, expected, flag, call_wrapper); |
+ InvokeFunctionCode(edi, no_reg, expected, expected, flag, call_wrapper); |
} |
@@ -2091,16 +2137,6 @@ void MacroAssembler::GetBuiltinFunction(Register target, |
} |
-void MacroAssembler::GetBuiltinEntry(Register target, |
- int native_context_index) { |
- DCHECK(!target.is(edi)); |
- // Load the JavaScript builtin function from the builtins object. |
- GetBuiltinFunction(edi, native_context_index); |
- // Load the code entry point from the function into the target register. |
- mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
-} |
- |
- |
void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
if (context_chain_length > 0) { |
// Move up the chain of contexts to the context containing the slot. |