Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(603)

Unified Diff: src/builtins/x87/builtins-x87.cc

Issue 2293253007: X87: [Interpreter] Collect type feedback for 'new' in the bytecode handler. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/x87/interface-descriptors-x87.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/x87/builtins-x87.cc
diff --git a/src/builtins/x87/builtins-x87.cc b/src/builtins/x87/builtins-x87.cc
index 5cc72ee64061153dd5b68818292f7849cf2eb777..2b7dfdd46ed262ce2bdac870e61d1a80e3bffbfb 100644
--- a/src/builtins/x87/builtins-x87.cc
+++ b/src/builtins/x87/builtins-x87.cc
@@ -705,19 +705,20 @@ void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
}
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
- Register array_limit) {
+ Register array_limit,
+ Register start_address) {
// ----------- S t a t e -------------
- // -- ebx : Pointer to the last argument in the args array.
+ // -- start_address : Pointer to the last argument in the args array.
// -- array_limit : Pointer to one before the first argument in the
// args array.
// -----------------------------------
Label loop_header, loop_check;
__ jmp(&loop_check);
__ bind(&loop_header);
- __ Push(Operand(ebx, 0));
- __ sub(ebx, Immediate(kPointerSize));
+ __ Push(Operand(start_address, 0));
+ __ sub(start_address, Immediate(kPointerSize));
__ bind(&loop_check);
- __ cmp(ebx, array_limit);
+ __ cmp(start_address, array_limit);
__ j(greater, &loop_header, Label::kNear);
}
@@ -743,7 +744,8 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
__ neg(ecx);
__ add(ecx, ebx);
- Generate_InterpreterPushArgs(masm, ecx);
+ // TODO(mythria): Add a stack check before pushing the arguments.
+ Generate_InterpreterPushArgs(masm, ecx, ebx);
// Call the target.
__ Push(edx); // Re-push return address.
@@ -761,40 +763,119 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
}
// static
-void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
+void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
+ MacroAssembler* masm, CallableType construct_type) {
// ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver)
// -- edx : the new target
// -- edi : the constructor
- // -- ebx : the address of the first argument to be pushed. Subsequent
+ // -- ebx : allocation site feedback (if available or undefined)
+ // -- ecx : the address of the first argument to be pushed. Subsequent
// arguments should be consecutive above this, in the same order as
// they are to be pushed onto the stack.
// -----------------------------------
- // Pop return address to allow tail-call after pushing arguments.
- __ Pop(ecx);
-
- // Push edi in the slot meant for receiver. We need an extra register
- // so store edi temporarily on stack.
+ // Store edi, edx onto the stack. We need two extra registers
+ // so store edi, edx temporarily on stack.
__ Push(edi);
+ __ Push(edx);
- // Find the address of the last argument.
- __ mov(edi, eax);
- __ neg(edi);
- __ shl(edi, kPointerSizeLog2);
- __ add(edi, ebx);
-
- Generate_InterpreterPushArgs(masm, edi);
+ // We have to pop return address and the two temporary registers before we
+ // can push arguments onto the stack. we do not have any free registers so
+ // update the stack and copy them into the correct places on the stack.
+ // current stack =====> required stack layout
+ // | | | edx | (2) <-- esp(1)
+ // | | | edi | (3)
+ // | | | return addr | (4)
+ // | | | arg N | (5)
+ // | edx | <-- esp | .... |
+ // | edi | | arg 0 |
+ // | return addr | | receiver slot |
+
+ // First increment the stack pointer to the correct location.
+ // we need additional slots for arguments and the receiver.
+ // Step 1 - compute the required increment to the stack.
+ __ mov(edx, eax);
+ __ shl(edx, kPointerSizeLog2);
+ __ add(edx, Immediate(kPointerSize));
+
+#ifdef _MSC_VER
+ // TODO(mythria): Move it to macro assembler.
+ // In windows, we cannot increment the stack size by more than one page
+ // (mimimum page size is 4KB) without accessing at least one byte on the
+ // page. Check this:
+ // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx.
+ const int page_size = 4 * 1024;
+ Label check_offset, update_stack_pointer;
+ __ bind(&check_offset);
+ __ cmp(edx, page_size);
+ __ j(less, &update_stack_pointer);
+ __ sub(esp, Immediate(page_size));
+ // Just to touch the page, before we increment further.
+ __ mov(Operand(esp, 0), Immediate(0));
+ __ sub(edx, Immediate(page_size));
+ __ jmp(&check_offset);
+ __ bind(&update_stack_pointer);
+#endif
+
+ // TODO(mythria): Add a stack check before updating the stack pointer.
+
+ // Step 1 - Update the stack pointer.
+ __ sub(esp, edx);
+
+ // Step 2 move edx to the correct location. Move edx first otherwise
+ // we may overwrite when eax = 0 or 1, basically when the source and
+ // destination overlap. We at least need one extra slot for receiver,
+ // so no extra checks are required to avoid copy.
+ __ mov(edi, Operand(esp, eax, times_pointer_size, 1 * kPointerSize));
+ __ mov(Operand(esp, 0), edi);
+
+ // Step 3 move edi to the correct location
+ __ mov(edi, Operand(esp, eax, times_pointer_size, 2 * kPointerSize));
+ __ mov(Operand(esp, 1 * kPointerSize), edi);
+
+ // Step 4 move return address to the correct location
+ __ mov(edi, Operand(esp, eax, times_pointer_size, 3 * kPointerSize));
+ __ mov(Operand(esp, 2 * kPointerSize), edi);
+
+ // Slot meant for receiver contains return address. Reset it so that
+ // we will not incorrectly interpret return address as an object.
+ __ mov(Operand(esp, eax, times_pointer_size, 3 * kPointerSize), Immediate(0));
+
+ // Step 5 copy arguments to correct locations.
+ __ mov(edx, eax);
- // Restore the constructor from slot on stack. It was pushed at the slot
- // meant for receiver.
- __ mov(edi, Operand(esp, eax, times_pointer_size, 0));
+ Label loop_header, loop_check;
+ __ jmp(&loop_check);
+ __ bind(&loop_header);
+ __ mov(edi, Operand(ecx, 0));
+ __ mov(Operand(esp, edx, times_pointer_size, 2 * kPointerSize), edi);
+ __ sub(ecx, Immediate(kPointerSize));
+ __ sub(edx, Immediate(1));
+ __ bind(&loop_check);
+ __ cmp(edx, Immediate(0));
+ __ j(greater, &loop_header, Label::kNear);
- // Re-push return address.
- __ Push(ecx);
+ // Restore edi and edx.
+ __ Pop(edx);
+ __ Pop(edi);
+
+ __ AssertUndefinedOrAllocationSite(ebx);
+ if (construct_type == CallableType::kJSFunction) {
+ // Tail call to the function-specific construct stub (still in the caller
+ // context at this point).
+ __ AssertFunction(edi);
+
+ __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+ __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset));
+ __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
+ __ jmp(ecx);
+ } else {
+ DCHECK_EQ(construct_type, CallableType::kAny);
- // Call the constructor with unmodified eax, edi, ebi values.
- __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
+ // Call the constructor with unmodified eax, edi, edx values.
+ __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
+ }
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
« no previous file with comments | « no previous file | src/x87/interface-descriptors-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698