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

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

Issue 2571563004: [Turbofan] Implement super calls with spread bytecode in assembly code. (Closed)
Patch Set: Rebase on master Created 4 years 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 | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/x64/builtins-x64.cc
diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc
index a292d70c71c6a4cd4878b9321ba12b078427e311..ca1b222441766bc165fdf335348782c07935b3f5 100644
--- a/src/builtins/x64/builtins-x64.cc
+++ b/src/builtins/x64/builtins-x64.cc
@@ -2883,6 +2883,114 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
RelocInfo::CODE_TARGET);
}
+// static
+void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : the number of arguments (not including the receiver)
+ // -- rdx : the new target (either the same as the constructor or
+ // the JSFunction on which new was invoked initially)
+ // -- rdi : the constructor to call (can be any Object)
+ // -----------------------------------
+
+ // Make sure the target is actually a constructor.
+ Label target_not_constructor;
Benedikt Meurer 2016/12/15 11:59:52 These checks must not be performed before the eval
petermarshall 2016/12/15 13:37:27 Yep cool
+ __ JumpIfSmi(rdi, &target_not_constructor, Label::kFar);
+ __ movp(rcx, FieldOperand(rdi, HeapObject::kMapOffset));
+ __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
+ Immediate(1 << Map::kIsConstructor));
+ __ j(zero, &target_not_constructor, Label::kFar);
+
+ // Make sure the new target is actually a constructor.
+ Label new_target_not_constructor;
Benedikt Meurer 2016/12/15 11:59:52 Same for new.target
+ __ JumpIfSmi(rdx, &new_target_not_constructor, Label::kFar);
+ __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
+ __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
+ Immediate(1 << Map::kIsConstructor));
+ __ j(zero, &new_target_not_constructor, Label::kFar);
+
+ // Load the spread argument.
+ __ movp(rbx, Operand(rsp, kPointerSize));
+ {
+ // Call the builtin for the result of the spread.
+ FrameScope scope(masm, StackFrame::INTERNAL);
+ __ Push(rdi); // target
+ __ Push(rdx); // new target
+ __ Integer32ToSmi(rax, rax);
+ __ Push(rax); // nargs
+ __ Push(rbx);
+ __ CallRuntime(Runtime::kSpreadIterablePrepareFixed);
+ __ movp(rbx, rax);
+ __ Pop(rax); // nargs
+ __ SmiToInteger32(rax, rax);
+ __ Pop(rdx); // new target
+ __ Pop(rdi); // target
+ }
+
+ {
+ // Pop the return address and spread argument.
+ __ PopReturnAddressTo(r8);
+ __ Pop(rcx);
+
+ // Calculate the new nargs including the result of the spread.
+ __ SmiToInteger32(r9, FieldOperand(rbx, FixedArray::kLengthOffset));
+ __ addp(rax, r9);
Benedikt Meurer 2016/12/15 11:59:52 You can combine these addp and subp into a single
petermarshall 2016/12/15 13:37:27 I always thought leap was a funny instruction name
+ __ subp(rax, Immediate(1)); // Subtract 1 for the spread itself.
+ }
+
+ // Check for stack overflow.
+ {
+ // Check the stack for overflow. We are not trying to catch interruptions
+ // (i.e. debug break and preemption) here, so check the "real stack limit".
+ Label done;
+ __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
+ __ movp(rcx, rsp);
+ // Make rcx the space we have left. The stack might already be overflowed
+ // here which will cause rcx to become negative.
+ __ subp(rcx, kScratchRegister);
+ __ sarp(rcx, Immediate(kPointerSizeLog2));
+ // Check if the arguments will overflow the stack.
+ __ cmpp(rcx, r9);
+ __ j(greater, &done, Label::kNear); // Signed comparison.
+ __ TailCallRuntime(Runtime::kThrowStackOverflow);
+ __ bind(&done);
+ }
+
+ // Put the evaluated spread onto the stack as additional arguments.
+ {
+ __ Set(rcx, 0);
+ Label done, loop;
+ __ bind(&loop);
+ __ cmpl(rcx, r9);
+ __ j(equal, &done, Label::kNear);
+ __ movp(kScratchRegister, FieldOperand(rbx, rcx, times_pointer_size,
+ FixedArray::kHeaderSize));
+ __ Push(kScratchRegister);
+ __ incl(rcx);
+ __ jmp(&loop);
+ __ bind(&done);
+ __ PushReturnAddressFrom(r8);
+ }
+
+ // Dispatch
+ { __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); }
+
+ // The target is not a constructor, throw an appropriate TypeError.
+ __ bind(&target_not_constructor);
+ {
+ StackArgumentsAccessor args(rsp, 0);
+ __ movp(args.GetReceiverOperand(), rdi);
+ __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
+ }
+
+ // The new.target is not a constructor, throw an appropriate TypeError.
+ __ bind(&new_target_not_constructor);
+ {
+ StackArgumentsAccessor args(rsp, 0);
+ __ movp(args.GetReceiverOperand(), rdx);
+ __ TailCallRuntime(Runtime::kThrowCalledNonCallable);
+ }
+}
+
static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
Register function_template_info,
Register scratch0, Register scratch1,
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698