1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X87 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/full-codegen/full-codegen.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/x87/frames-x87.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_Adaptor(MacroAssembler* masm, Address address, 19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExitFrameType exit_frame_type) { 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- eax : number of arguments excluding receiver 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[0] : return address 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[4] : last argument 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ... 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4 * argc] : first argument 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[4 * (argc +1)] : receiver 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(edi); 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure we operate in the context of the called function (for example 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ConstructStubs implemented in C++ will be run in the context of the caller 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // instead of the callee, due to the way that [[Construct]] is defined for 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ordinary functions). 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // JumpToExternalReference expects eax to contain the number of arguments 39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // including the receiver and the extra arguments. 40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch const int num_extra_args = 3; 41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ add(eax, Immediate(num_extra_args + 1)); 42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Insert extra arguments. 4413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ PopReturnAddressTo(ecx); 45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(eax); 46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(eax); 47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(eax); 4813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edi); 4913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edx); 5013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ PushReturnAddressFrom(ecx); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpToExternalReference(ExternalReference(address, masm->isolate()), 53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch exit_frame_type == BUILTIN_EXIT); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 56109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void GenerateTailCallToReturnedCode(MacroAssembler* masm, 57109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Runtime::FunctionId function_id) { 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 59109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- eax : argument count (preserved for callee) 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new target (preserved for callee) 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target function (preserved for callee) 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 63109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 64109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 65109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Push the number of arguments to the callee. 66109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(eax); 67109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(eax); 68109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Push a copy of the target function and the new target. 69109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(edi); 70109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(edx); 71109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Function is also the parameter to the runtime call. 72109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(edi); 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 74109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(function_id, 1); 75109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, eax); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 77109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore target function and new target. 78109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pop(edx); 79109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pop(edi); 80109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pop(eax); 81109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(eax); 82109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 83f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 84109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); 85109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(ebx); 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) { 89109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 90109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kCodeOffset)); 91109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); 92109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(ebx); 93f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 94f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checking whether the queued function is ready for install is optional, 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // since we come across interrupts and stack checks elsewhere. However, 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not checking may delay installing ready functions, and always checking 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // would be quite expensive. A good compromise is to first check against 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stack limit as a cue for an interrupt signal. 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference stack_limit = 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_stack_limit(masm->isolate()); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(esp, Operand::StaticVariable(stack_limit)); 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, &ok, Label::kNear); 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kTryInstallOptimizedCode); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateTailCallToSharedCode(masm); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 113c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace { 114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid Generate_JSConstructStubHelper(MacroAssembler* masm, bool is_api_function, 116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool create_implicit_receiver, 117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch bool check_derived_construct) { 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- eax: number of arguments 1203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // -- esi: context 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- edi: constructor function 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx: new target 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enter a construct frame. 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::CONSTRUCT); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Preserve the incoming parameters on the stack. 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiTag(eax); 131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ push(esi); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver) { 135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocate the new receiver object. 136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(edi); 137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(edx); 13862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(CodeFactory::FastNewObject(masm->isolate()).code(), 13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, eax); 141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(edx); 142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(edi); 143f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch 144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 145109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- edi: constructor function 146109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- ebx: newly allocated object 147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- edx: new target 148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Retrieve smi-tagged arguments count from the stack. 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Operand(esp, 0)); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(eax); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver) { 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the allocated receiver to the stack. We need two copies 158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // because we may have to return the original one and the calling 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // conventions dictate that the called function pops the receiver. 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(ebx); 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(ebx); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushRoot(Heap::kTheHoleValueRootIndex); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set up pointer to last argument. 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy arguments and receiver to the expression stack. 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop, entry; 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, eax); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&entry); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebx, ecx, times_4, 0)); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&entry); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(ecx); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater_equal, &loop); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the function. 180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ParameterCount actual(eax); 181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ InvokeFunction(edi, edx, actual, CALL_FUNCTION, 182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CheckDebugStepCallWrapper()); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store offset of return address for deoptimizer. 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver && !is_api_function) { 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore context from the frame. 1903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset)); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver) { 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the result is an object (in the ECMA sense), we should get rid 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // of the receiver and use the result; see ECMA-262 section 13.2.2-7 195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // on page 74. 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label use_receiver, exit; 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the result is a smi, it is *not* an object in the ECMA sense. 199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ JumpIfSmi(eax, &use_receiver, Label::kNear); 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the type of the result (stored in its map) is less than 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense. 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx); 204c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(above_equal, &exit, Label::kNear); 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Throw away the result of the constructor invocation and use the 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // on-stack receiver as the result. 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&use_receiver); 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Operand(esp, 0)); 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore the arguments count and leave the construct frame. The 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments count is stored below the receiver. 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&exit); 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, 1 * kPointerSize)); 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, 0)); 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave construct frame. 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ES6 9.2.2. Step 13+ 223109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the result is not a Smi, indicating that the constructor result 224109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // from a derived class is neither undefined nor an Object. 225109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (check_derived_construct) { 226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label dont_throw; 227109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfNotSmi(eax, &dont_throw); 228109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 230109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kThrowDerivedConstructorReturnedNonObject); 231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&dont_throw); 233109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 234109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove caller arguments from the stack and return. 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(ecx); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ecx); 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver) { 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} // namespace 247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, false, true, false); 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 253109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, true, false, false); 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) { 257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, false, false, false); 258109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 260109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_JSBuiltinsConstructStubForDerived( 261109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm) { 262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, false, false, true); 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) { 266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edi); 268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowConstructedNonConstructable); 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochenum IsTagged { kEaxIsSmiTagged, kEaxIsUntaggedInt }; 272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Clobbers ecx, edx, edi; preserves all other registers. 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void Generate_CheckStackOverflow(MacroAssembler* masm, 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IsTagged eax_is_tagged) { 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax : the number of items to be pushed to the stack 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check the stack for overflow. We are not trying to catch 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // limit" is checked. 281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label okay; 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference real_stack_limit = 283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand::StaticVariable(real_stack_limit)); 285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make ecx the space we have left. The stack might already be overflowed 286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // here which will cause ecx to become negative. 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, esp); 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(ecx, edi); 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make edx the space we need for the array when it is unrolled onto the 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // stack. 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, eax); 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int smi_tag = eax_is_tagged == kEaxIsSmiTagged ? kSmiTagSize : 0; 293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ shl(edx, kPointerSizeLog2 - smi_tag); 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the arguments will overflow the stack. 295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, edx); 296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &okay); // Signed comparison. 297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Out of stack space. 299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&okay); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_construct) { 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Setup the context (we need to use the caller context from the isolate). 312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference context_address(Isolate::kContextAddress, 313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm->isolate()); 314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, Operand::StaticVariable(context_address)); 315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the previous frame pointer (ebx) to access C arguments 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(ebp, 0)); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the function and the receiver onto the stack. 320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the number of arguments and setup pointer to the arguments. 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if we have enough stack space to push all arguments. 328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Expects argument count in eax. Clobbers ecx, edx, edi. 329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_CheckStackOverflow(masm, kEaxIsUntaggedInt); 330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy arguments to the stack in a loop. 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop, entry; 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(ecx, Immediate(0)); 334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&entry, Label::kNear); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv 337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(Operand(edx, 0)); // dereference handle 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ inc(ecx); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&entry); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, eax); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &loop); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the previous frame pointer (ebx) to access C arguments 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(ebp, 0)); 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the new.target and function from the frame. 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(ebx, EntryFrameConstants::kNewTargetArgOffset)); 348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Invoke the code. 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Code> builtin = is_construct 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ? masm->isolate()->builtins()->Construct() 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : masm->isolate()->builtins()->Call(); 354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(builtin, RelocInfo::CODE_TARGET); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exit the internal frame. Notice that this also removes the empty. 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // context and the function left on the stack by the code 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // invocation. 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(kPointerSize); // Remove receiver. 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_JSEntryTrampolineHelper(masm, false); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_JSEntryTrampolineHelper(masm, true); 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// static 372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { 373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- eax : the value to pass to the generator 375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- ebx : the JSGeneratorObject to resume 376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : the resume mode (tagged) 377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esp[0] : return address 378bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ AssertGeneratorObject(ebx); 380bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 381bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Store input value into generator object. 38213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOrDebugPosOffset), eax); 38313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ RecordWriteField(ebx, JSGeneratorObject::kInputOrDebugPosOffset, eax, ecx, 384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kDontSaveFPRegs); 385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Store resume mode into generator object. 387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(ebx, JSGeneratorObject::kResumeModeOffset), edx); 388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load suspended function and context. 390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); 39162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Flood function if we are stepping. 39413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator; 39513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label stepping_prepared; 39662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalReference debug_hook = 39762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ExternalReference::debug_hook_on_function_call_address(masm->isolate()); 39862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmpb(Operand::StaticVariable(debug_hook), Immediate(0)); 39962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &prepare_step_in_if_stepping); 40013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 40113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Flood function if we need to continue stepping in the suspended generator. 40213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ExternalReference debug_suspended_generator = 40313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ExternalReference::debug_suspended_generator_address(masm->isolate()); 40413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ cmp(ebx, Operand::StaticVariable(debug_suspended_generator)); 40513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ j(equal, &prepare_step_in_suspended_generator); 40613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ bind(&stepping_prepared); 407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 408bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Pop return address. 409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PopReturnAddressTo(eax); 410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 411bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Push receiver. 412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset)); 413bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- eax : return address 416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- ebx : the JSGeneratorObject to resume 417bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : the resume mode (tagged) 418bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edi : generator function 419bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esi : generator context 420bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esp[0] : generator receiver 421bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 422bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 423bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Push holes for arguments to generator function. Since the parser forced 424bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // context allocation for any variables in generators, the actual argument 425bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // values have already been copied into the context and these dummy values 426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // will never be used. 427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 428bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, 429bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset)); 430bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 431bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label done_loop, loop; 432bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&loop); 433bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ sub(ecx, Immediate(Smi::FromInt(1))); 434bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(carry, &done_loop, Label::kNear); 435bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushRoot(Heap::kTheHoleValueRootIndex); 436bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(&loop); 437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&done_loop); 438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 44062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Underlying function needs to have bytecode available. 44162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (FLAG_debug_code) { 44262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 44362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kFunctionDataOffset)); 44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ CmpObjectType(ecx, BYTECODE_ARRAY_TYPE, ecx); 44562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Assert(equal, kMissingBytecodeArray); 44662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 44862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Resume (Ignition/TurboFan) generator object. 449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(eax); 451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(eax, 45362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FieldOperand(eax, SharedFunctionInfo::kFormalParameterCountOffset)); 454bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // We abuse new.target both to indicate that this is a resume call and to 455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // pass in the generator object. In ordinary calls, new.target is always 456bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // undefined because generator functions are non-constructable. 457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(edx, ebx); 458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(FieldOperand(edi, JSFunction::kCodeEntryOffset)); 459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 46113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ bind(&prepare_step_in_if_stepping); 46213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 46313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 46413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(ebx); 46513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edx); 46613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edi); 46762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ CallRuntime(Runtime::kDebugOnFunctionCall); 46813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(edx); 46913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(ebx); 47013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); 47113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 47213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ jmp(&stepping_prepared); 47313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 47413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ bind(&prepare_step_in_suspended_generator); 47513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 47613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 47713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(ebx); 47813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edx); 47913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator); 48013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(edx); 48113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(ebx); 48213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); 48313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 48413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ jmp(&stepping_prepared); 48513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 48613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 48713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1, 48813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Register scratch2) { 48913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Register args_count = scratch1; 49013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Register return_pc = scratch2; 49113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 49213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Get the arguments + reciever count. 49313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(args_count, 49413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); 49513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(args_count, 49613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FieldOperand(args_count, BytecodeArray::kParameterSizeOffset)); 49713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 49813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Leave the frame (also dropping the register file). 49913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ leave(); 50013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 50113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Drop receiver + arguments. 50213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ pop(return_pc); 50313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ add(esp, args_count); 50413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ push(return_pc); 505bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Generate code for entering a JS function with the interpreter. 508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// On entry to the function the receiver and arguments have been pushed on the 509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// stack left to right. The actual argument count matches the formal parameter 510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// count expected by the function. 511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The live registers are: 513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o edi: the JS function object being called 514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o edx: the new target 515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o esi: our context 516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o ebp: the caller's frame pointer 517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o esp: stack pointer (pointing to return address) 518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 519109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// The function builds an interpreter frame. See InterpreterFrameConstants in 520109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// frames.h for its layout. 521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { 522bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the frame (that is done below). 527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame_scope(masm, StackFrame::MANUAL); 528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(ebp); // Caller's frame pointer. 529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebp, esp); 530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(esi); // Callee's context. 531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edi); // Callee's JS function. 532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edx); // Callee's new target. 533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 534bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Get the bytecode array from the function object (or from the DebugInfo if 535bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // it is present) and load it into kInterpreterBytecodeArrayRegister. 536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 537109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label load_debug_bytecode_array, bytecode_array_loaded; 53862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ JumpIfNotSmi(FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset), 53962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch &load_debug_bytecode_array); 540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(kInterpreterBytecodeArrayRegister, 541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset)); 542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&bytecode_array_loaded); 543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check whether we should continue to use the interpreter. 545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label switch_to_different_code_kind; 546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Move(ecx, masm->CodeObject()); // Self-reference to this code. 547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ cmp(ecx, FieldOperand(eax, SharedFunctionInfo::kCodeOffset)); 548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ j(not_equal, &switch_to_different_code_kind); 549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 550f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Increment invocation count for the function. 55162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ EmitLoadFeedbackVector(ecx); 55262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ add( 55362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FieldOperand(ecx, FeedbackVector::kInvocationCountIndex * kPointerSize + 55462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FeedbackVector::kHeaderSize), 55562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Immediate(Smi::FromInt(1))); 556f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 557bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check function data field is actually a BytecodeArray object. 558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code) { 559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(kInterpreterBytecodeArrayRegister); 560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE, 561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch eax); 562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); 563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 56562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Reset code age. 56662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov_b(FieldOperand(kInterpreterBytecodeArrayRegister, 56762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch BytecodeArray::kBytecodeAgeOffset), 56862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Immediate(BytecodeArray::kNoAgeBytecodeAge)); 56962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 570109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Push bytecode array. 571109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(kInterpreterBytecodeArrayRegister); 572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Push Smi tagged initial bytecode array offset. 573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(Immediate(Smi::FromInt(BytecodeArray::kHeaderSize - kHeapObjectTag))); 574109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate the local and temporary register file on the stack. 576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load frame size from the BytecodeArray object. 578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister, 579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BytecodeArray::kFrameSizeOffset)); 580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Do a stack check to ensure we don't go over the limit. 582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label ok; 583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, esp); 584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(ecx, ebx); 585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference stack_limit = 586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, Operand::StaticVariable(stack_limit)); 588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above_equal, &ok); 589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&ok); 591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If ok, push undefined as the initial value for all register file entries. 593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop_header; 594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop_check; 595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value())); 596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&loop_check); 597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_header); 598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(rmcilroy): Consider doing more than one push per loop iteration. 599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(eax); 600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Continue loop if not done. 601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_check); 602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(ebx, Immediate(kPointerSize)); 603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater_equal, &loop_header); 604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load accumulator, bytecode offset and dispatch table into registers. 607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex); 608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(kInterpreterBytecodeOffsetRegister, 609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag)); 610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterDispatchTableRegister, 611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(ExternalReference::interpreter_dispatch_table_address( 612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()))); 613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch to the first bytecode handler for the function. 615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, 616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch kInterpreterBytecodeOffsetRegister, times_1, 0)); 617bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, 618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch times_pointer_size, 0)); 619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ call(ebx); 620bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset()); 621109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The return value is in eax. 62313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LeaveInterpreterFrame(masm, ebx, ecx); 624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ret(0); 625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 626bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load debug copy of the bytecode array. 627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&load_debug_bytecode_array); 628bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register debug_info = kInterpreterBytecodeArrayRegister; 629bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(debug_info, FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset)); 630bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterBytecodeArrayRegister, 631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FieldOperand(debug_info, DebugInfo::kDebugBytecodeArrayIndex)); 632bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(&bytecode_array_loaded); 633bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 634f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the shared code is no longer this entry trampoline, then the underlying 635f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // function has been switched to a different kind of code and we heal the 636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // closure by switching the code entry field over to the new code as well. 637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&switch_to_different_code_kind); 638bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(edx); // Callee's new target. 639bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(edi); // Callee's JS function. 640bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(esi); // Callee's context. 641bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ leave(); // Leave the frame so we can tail call. 642bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset)); 644bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 645bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(edi, JSFunction::kCodeEntryOffset), ecx); 646bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteCodeEntryField(edi, ecx, ebx); 647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(ecx); 648bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 650f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, 651f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register scratch1, Register scratch2, 652f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* stack_overflow, 653f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool include_receiver = false) { 654f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check the stack for overflow. We are not trying to catch 655f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 656f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // limit" is checked. 657f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ExternalReference real_stack_limit = 658f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 659f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, Operand::StaticVariable(real_stack_limit)); 660f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Make scratch2 the space we have left. The stack might already be overflowed 661f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // here which will cause scratch2 to become negative. 662f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch2, esp); 663f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(scratch2, scratch1); 664f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Make scratch1 the space we need for the array when it is unrolled onto the 665f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // stack. 666f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, num_args); 667f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (include_receiver) { 668f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(scratch1, Immediate(1)); 669f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 670f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ shl(scratch1, kPointerSizeLog2); 671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if the arguments will overflow the stack. 672f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(scratch2, scratch1); 673f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ j(less_equal, stack_overflow); // Signed comparison. 674f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 675f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void Generate_InterpreterPushArgs(MacroAssembler* masm, 677f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register array_limit, 678f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register start_address) { 679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 680f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- start_address : Pointer to the last argument in the args array. 681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- array_limit : Pointer to one before the first argument in the 682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // args array. 683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop_header, loop_check; 685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&loop_check); 686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_header); 687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(Operand(start_address, 0)); 688f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(start_address, Immediate(kPointerSize)); 689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_check); 690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(start_address, array_limit); 691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &loop_header, Label::kNear); 692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_InterpreterPushArgsAndCallImpl( 696f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MacroAssembler* masm, TailCallMode tail_call_mode, 69762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch InterpreterPushArgsMode mode) { 698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ebx : the address of the first argument to be pushed. Subsequent 701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments should be consecutive above this, in the same order as 702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // they are to be pushed onto the stack. 703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the target to call (can be any Object). 704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label stack_overflow; 706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Compute the expected number of arguments. 707f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(ecx, eax); 708f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(ecx, Immediate(1)); // Add one for receiver. 709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 710f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Add a stack check before pushing the arguments. We need an extra register 711f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // to perform a stack check. So push it onto the stack temporarily. This 712f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // might cause stack overflow, but it will be detected by the check. 713f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edi); 714f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, ecx, edx, edi, &stack_overflow); 715f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Pop return address to allow tail-call after pushing arguments. 718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Find the address of the last argument. 721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ shl(ecx, kPointerSizeLog2); 722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(ecx); 723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ecx, ebx); 724f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_InterpreterPushArgs(masm, ecx, ebx); 725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the target. 727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); // Re-push return address. 728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 72962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode == InterpreterPushArgsMode::kJSFunction) { 730f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, 731f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tail_call_mode), 732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RelocInfo::CODE_TARGET); 73362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) { 73462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Jump(masm->isolate()->builtins()->CallWithSpread(), 73562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 736f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, 738f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tail_call_mode), 739f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RelocInfo::CODE_TARGET); 740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 741f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 742f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&stack_overflow); 743f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 744f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pop the temporary registers, so that return address is on top of stack. 745f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This should be unreachable. 750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ int3(); 751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 752f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 753f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 754f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace { 755f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 756f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// This function modified start_addr, and only reads the contents of num_args 757f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// register. scratch1 and scratch2 are used as temporary registers. Their 758f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// original values are restored after the use. 759f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Generate_InterpreterPushArgsAndReturnAddress( 760f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MacroAssembler* masm, Register num_args, Register start_addr, 761f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register scratch1, Register scratch2, bool receiver_in_args, 762f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int num_slots_above_ret_addr, Label* stack_overflow) { 763f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We have to move return address and the temporary registers above it 764f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // before we can copy arguments onto the stack. To achieve this: 765f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 1: Increment the stack pointer by num_args + 1 (for receiver). 766f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 2: Move the return address and values above it to the top of stack. 767f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 3: Copy the arguments into the correct locations. 768f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // current stack =====> required stack layout 769f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | scratch1 | (2) <-- esp(1) 770f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | .... | (2) 771f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | scratch-n | (2) 772f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | return addr | (2) 773f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | arg N | (3) 774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | scratch1 | <-- esp | .... | 775f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | .... | | arg 0 | 776f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | scratch-n | | arg 0 | 777f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | return addr | | receiver slot | 778f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 779f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check for stack overflow before we increment the stack pointer. 780f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, num_args, scratch1, scratch2, 781f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch stack_overflow, true); 782f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 783f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Step 1 - Update the stack pointer. scratch1 already contains the required 784f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// increment to the stack. i.e. num_args + 1 stack slots. This is computed in 785f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// the Generate_StackOverflowCheck. 786f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 787f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#ifdef _MSC_VER 788f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(mythria): Move it to macro assembler. 789f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // In windows, we cannot increment the stack size by more than one page 790f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // (mimimum page size is 4KB) without accessing at least one byte on the 791f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // page. Check this: 792f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. 793f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const int page_size = 4 * 1024; 794f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label check_offset, update_stack_pointer; 795f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&check_offset); 796f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(scratch1, page_size); 797f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ j(less, &update_stack_pointer); 798f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(esp, Immediate(page_size)); 799f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Just to touch the page, before we increment further. 800f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, 0), Immediate(0)); 801f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(scratch1, Immediate(page_size)); 802f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(&check_offset); 803f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&update_stack_pointer); 804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif 805f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 806f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(esp, scratch1); 807f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 808f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 2 move return_address and slots above it to the correct locations. 809f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Move from top to bottom, otherwise we may overwrite when num_args = 0 or 1, 810f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // basically when the source and destination overlap. We at least need one 811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // extra slot for receiver, so no extra checks are required to avoid copy. 812f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch for (int i = 0; i < num_slots_above_ret_addr + 1; i++) { 813f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, 814f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Operand(esp, num_args, times_pointer_size, (i + 1) * kPointerSize)); 815f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, i * kPointerSize), scratch1); 816f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 817f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 818f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 3 copy arguments to correct locations. 819f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (receiver_in_args) { 820f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, num_args); 821f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(scratch1, Immediate(1)); 822f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 823f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Slot meant for receiver contains return address. Reset it so that 824f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // we will not incorrectly interpret return address as an object. 825f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, num_args, times_pointer_size, 826f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch (num_slots_above_ret_addr + 1) * kPointerSize), 827f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Immediate(0)); 828f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, num_args); 829f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 830f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 831f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label loop_header, loop_check; 832f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(&loop_check); 833f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&loop_header); 834f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch2, Operand(start_addr, 0)); 835f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, scratch1, times_pointer_size, 836f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch num_slots_above_ret_addr * kPointerSize), 837f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch scratch2); 838f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(start_addr, Immediate(kPointerSize)); 839f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(scratch1, Immediate(1)); 840f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&loop_check); 841f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(scratch1, Immediate(0)); 842f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ j(greater, &loop_header, Label::kNear); 843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 845f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} // end anonymous namespace 846f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 848f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Builtins::Generate_InterpreterPushArgsAndConstructImpl( 84962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch MacroAssembler* masm, InterpreterPushArgsMode mode) { 850014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 851014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target 853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor 854f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ebx : allocation site feedback (if available or undefined) 855f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ecx : the address of the first argument to be pushed. Subsequent 856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments should be consecutive above this, in the same order as 857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // they are to be pushed onto the stack. 858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 859f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label stack_overflow; 860f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We need two scratch registers. Push edi and edx onto stack. 861f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edi); 862f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edx); 863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 864f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Push arguments and move return address to the top of stack. 865f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The eax register is readonly. The ecx register will be modified. The edx 866f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // and edi registers will be modified but restored to their original values. 867f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, 868f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2, &stack_overflow); 869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 870f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Restore edi and edx 871f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 872f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 873f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 874f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ AssertUndefinedOrAllocationSite(ebx); 87562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (mode == InterpreterPushArgsMode::kJSFunction) { 876f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Tail call to the function-specific construct stub (still in the caller 877f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // context at this point). 878f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ AssertFunction(edi); 879f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 880f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 881f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 882f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 883f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(ecx); 88462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) { 88562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Call the constructor with unmodified eax, edi, edx values. 88662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Jump(masm->isolate()->builtins()->ConstructWithSpread(), 88762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 888f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 88962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(InterpreterPushArgsMode::kOther, mode); 890f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Call the constructor with unmodified eax, edi, edx values. 891f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 892f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 893f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 894f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&stack_overflow); 895f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 896f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pop the temporary registers, so that return address is on top of stack. 897f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 898f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 899f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 900f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 901f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 902f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This should be unreachable. 903f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ int3(); 904f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 905f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 906f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 907f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// static 908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Builtins::Generate_InterpreterPushArgsAndConstructArray( 909f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MacroAssembler* masm) { 910f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // ----------- S t a t e ------------- 911f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- eax : the number of arguments (not including the receiver) 912f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- edx : the target to call checked to be Array function. 913f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ebx : the allocation site feedback 914f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ecx : the address of the first argument to be pushed. Subsequent 915f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // arguments should be consecutive above this, in the same order as 916f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // they are to be pushed onto the stack. 917f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // ----------------------------------- 918f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label stack_overflow; 919f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We need two scratch registers. Register edi is available, push edx onto 920f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // stack. 921f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edx); 922f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 923f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Push arguments and move return address to the top of stack. 924f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The eax register is readonly. The ecx register will be modified. The edx 925f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // and edi registers will be modified but restored to their original values. 926f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true, 927f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1, &stack_overflow); 928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 929f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Restore edx. 930f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 932f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Array constructor expects constructor in edi. It is same as edx here. 933f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Move(edi, edx); 934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 935f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ArrayConstructorStub stub(masm->isolate()); 936f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallStub(&stub); 937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 938f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&stack_overflow); 939f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 940f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pop the temporary registers, so that return address is on top of stack. 941f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 942f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 943f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 944f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 945f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This should be unreachable. 946f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ int3(); 947f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 950c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstatic void Generate_InterpreterEnterBytecode(MacroAssembler* masm) { 951bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Set the return address to the correct point in the interpreter entry 952bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // trampoline. 953bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Smi* interpreter_entry_return_pc_offset( 954bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()->heap()->interpreter_entry_return_pc_offset()); 955c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_NE(interpreter_entry_return_pc_offset, Smi::kZero); 956bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadHeapObject(ebx, 957bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()->builtins()->InterpreterEntryTrampoline()); 958bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() + 959bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::kHeaderSize - kHeapObjectTag)); 960bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(ebx); 961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 962bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Initialize the dispatch table register. 963bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterDispatchTableRegister, 964bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(ExternalReference::interpreter_dispatch_table_address( 965bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()))); 966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the bytecode array pointer from the frame. 968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(kInterpreterBytecodeArrayRegister, 969bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); 970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code) { 972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check function data field is actually a BytecodeArray object. 973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(kInterpreterBytecodeArrayRegister); 974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE, 975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ebx); 976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); 977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the target bytecode offset from the frame. 980bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterBytecodeOffsetRegister, 981bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp)); 982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(kInterpreterBytecodeOffsetRegister); 983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch to the target bytecode. 985bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, 986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch kInterpreterBytecodeOffsetRegister, times_1, 0)); 987bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, 988bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch times_pointer_size, 0)); 989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ebx); 990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 992c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid Builtins::Generate_InterpreterEnterBytecodeAdvance(MacroAssembler* masm) { 993c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Advance the current bytecode offset stored within the given interpreter 994c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // stack frame. This simulates what all bytecode handlers do upon completion 995c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // of the underlying operation. 996c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(ebx, Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); 997c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(edx, Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp)); 998c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 999c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 1000c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1001c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(kInterpreterAccumulatorRegister); 1002c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(ebx); // First argument is the bytecode array. 1003c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(edx); // Second argument is the bytecode offset. 1004c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ CallRuntime(Runtime::kInterpreterAdvanceBytecodeOffset); 1005c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(edx, eax); // Result is the new bytecode offset. 1006c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Pop(kInterpreterAccumulatorRegister); 1007c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1008c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp), edx); 1009c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Generate_InterpreterEnterBytecode(masm); 1011c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1012c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1013c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { 1014c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Generate_InterpreterEnterBytecode(masm); 1015c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1016c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_CompileLazy(MacroAssembler* masm) { 1018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 1019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- eax : argument count (preserved for callee) 1020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : new target (preserved for callee) 1021bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edi : target function (preserved for callee) 1022bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 1023bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // First lookup code, maybe we don't need to compile! 1024bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label gotta_call_runtime, gotta_call_runtime_no_stack; 1025bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label try_shared; 1026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label loop_top, loop_bottom; 1027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register closure = edi; 1029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register new_target = edx; 1030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register argument_count = eax; 1031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 103262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Do we have a valid feedback vector? 103362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ebx, FieldOperand(closure, JSFunction::kFeedbackVectorOffset)); 103462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ebx, FieldOperand(ebx, Cell::kValueOffset)); 103562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(ebx, masm->isolate()->factory()->undefined_value()); 103662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(equal, &gotta_call_runtime_no_stack); 103762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 1038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(argument_count); 1039bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(new_target); 1040bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(closure); 1041bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1042bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register map = argument_count; 1043bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register index = ebx; 1044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(map, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset)); 1045bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(map, FieldOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset)); 1046bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(index, FieldOperand(map, FixedArray::kLengthOffset)); 1047bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(index, Immediate(Smi::FromInt(2))); 104862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(less, &try_shared); 1049bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1050bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // edx : native context 1051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ebx : length / index 1052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // eax : optimized code map 1053bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // stack[0] : new target 1054bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // stack[4] : closure 1055bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register native_context = edx; 1056bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(native_context, NativeContextOperand()); 1057bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1058bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&loop_top); 1059bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register temp = edi; 1060bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1061bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Does the native context match? 1062bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(temp, FieldOperand(map, index, times_half_pointer_size, 1063bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SharedFunctionInfo::kOffsetToPreviousContext)); 1064bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset)); 1065bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(temp, native_context); 1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(not_equal, &loop_bottom); 1067bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Code available? 1068bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register entry = ecx; 1069bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(map, index, times_half_pointer_size, 1070bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SharedFunctionInfo::kOffsetToPreviousCachedCode)); 1071bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset)); 1072c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ JumpIfSmi(entry, &try_shared); 1073bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 107462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Found code. Get it into the closure and return. 1075bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(closure); 1076bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Store code entry in the closure. 1077bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ lea(entry, FieldOperand(entry, Code::kHeaderSize)); 1078bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry); 1079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteCodeEntryField(closure, entry, eax); 1080bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1081bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Link the closure into the optimized function list. 1082bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ecx : code entry 1083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // edx : native context 1084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // edi : closure 1085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, 1086bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST)); 1087bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), ebx); 1088bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, ebx, eax, 1089bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 1090bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch const int function_list_offset = 1091bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST); 1092bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST), 1093bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch closure); 1094bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Save closure before the write barrier. 1095bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, closure); 1096bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteContextSlot(native_context, function_list_offset, closure, eax, 1097bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kDontSaveFPRegs); 1098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(closure, ebx); 1099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(new_target); 1100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(argument_count); 1101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(entry); 1102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&loop_bottom); 1104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ sub(index, Immediate(Smi::FromInt(SharedFunctionInfo::kEntryLength))); 1105bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(index, Immediate(Smi::FromInt(1))); 1106bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(greater, &loop_top); 1107bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 110862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // We found no code. 1109bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(&gotta_call_runtime); 1110bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1111bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&try_shared); 1112c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ pop(closure); 1113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(new_target); 1114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(argument_count); 1115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset)); 1116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Is the shared function marked for tier up? 1117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ test_b(FieldOperand(entry, SharedFunctionInfo::kMarkedForTierUpByteOffset), 1118c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Immediate(1 << SharedFunctionInfo::kMarkedForTierUpBitWithinByte)); 1119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(not_zero, &gotta_call_runtime_no_stack); 112062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 112162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // If SFI points to anything other than CompileLazy, install that. 1122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(entry, SharedFunctionInfo::kCodeOffset)); 112362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Move(ebx, masm->CodeObject()); 112462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(entry, ebx); 1125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(equal, &gotta_call_runtime_no_stack); 112662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 112762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Install the SFI's code entry. 1128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ lea(entry, FieldOperand(entry, Code::kHeaderSize)); 1129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry); 1130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteCodeEntryField(closure, entry, ebx); 1131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(entry); 1132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&gotta_call_runtime); 1134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(closure); 1135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(new_target); 1136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(argument_count); 1137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&gotta_call_runtime_no_stack); 1138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy); 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_CompileBaseline(MacroAssembler* masm) { 1143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline); 1144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_CompileOptimized(MacroAssembler* masm) { 1147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateTailCallToReturnedCode(masm, 1148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Runtime::kCompileOptimized_NotConcurrent); 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) { 1152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileOptimized_Concurrent); 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) { 1156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------- S t a t e ------------- 1157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- eax : argument count (preserved for callee) 1158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- edx : new target (preserved for callee) 1159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- edi : target function (preserved for callee) 1160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------------------------------- 1161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label failed; 1162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Preserve argument count for later compare. 1165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ecx, eax); 1166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Push the number of arguments to the callee. 1167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(eax); 1168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(eax); 1169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Push a copy of the target function and the new target. 1170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(edi); 1171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(edx); 1172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The function. 1174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(edi); 1175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Copy arguments from caller (stdlib, foreign, heap). 1176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label args_done; 1177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int j = 0; j < 4; ++j) { 1178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label over; 1179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (j < 3) { 1180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ cmp(ecx, Immediate(j)); 1181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ j(not_equal, &over, Label::kNear); 1182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = j - 1; i >= 0; --i) { 1184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(Operand( 1185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ebp, StandardFrameConstants::kCallerSPOffset + i * kPointerSize)); 1186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0; i < 3 - j; ++i) { 1188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (j < 3) { 1191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&args_done, Label::kNear); 1192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&over); 1193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&args_done); 1196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Call runtime, on success unwind frame, and parent frame. 1198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kInstantiateAsmJs, 4); 1199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // A smi 0 is returned on failure, an object on success. 1200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfSmi(eax, &failed, Label::kNear); 1201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Drop(2); 1203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Pop(ecx); 1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ecx); 1205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch scope.GenerateLeaveFrame(); 1206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ebx); 1208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ inc(ecx); 1209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ecx, times_pointer_size, 0)); 1210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ebx); 1211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ret(0); 1212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&failed); 1214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Restore target function and new target. 1215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ pop(edx); 1216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ pop(edi); 1217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ pop(eax); 1218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(eax); 1219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // On failure, tail call back to regular js. 1221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy); 1222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For now, we are relying on the fact that make_code_young doesn't do any 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // garbage collection which allows us to save/restore the registers without 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // worrying about which of them contain pointers. We also don't build an 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // internal frame to make the code faster, since we shouldn't have to do stack 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // crawls in MakeCodeYoung. This seems a bit fragile. 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Re-execute the code that was patched back to the young age when 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the stub returns. 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(Operand(esp, 0), Immediate(5)); 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushad(); 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(esp, 8 * kPointerSize)); 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(2, ebx); 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 1 * kPointerSize), 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(ExternalReference::isolate_address(masm->isolate()))); 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), eax); 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::get_make_code_young_function(masm->isolate()), 2); 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popad(); 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 124962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \ 125062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch void Builtins::Generate_Make##C##CodeYoungAgain(MacroAssembler* masm) { \ 125162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); \ 1252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR) 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that make_code_young doesn't do any garbage collection which allows us to 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // save/restore the registers without worrying about which of them contain 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pointers. 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushad(); 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(esp, 8 * kPointerSize)); 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(eax, Immediate(Assembler::kCallInstructionLength)); 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { // NOLINT 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(2, ebx); 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 1 * kPointerSize), 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(ExternalReference::isolate_address(masm->isolate()))); 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), eax); 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::get_mark_code_as_executed_function(masm->isolate()), 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2); 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popad(); 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform prologue operations usually performed by the young code stub. 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); // Pop return address into scratch register. 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ebp); // Caller's frame pointer. 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebp, esp); 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(esi); // Callee's context. 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edi); // Callee's JS Function. 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); // Push return address after frame prologue. 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to point after the code-age stub. 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) { 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler* masm) { 1293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_MarkCodeAsExecutedOnce(masm); 1294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm, 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles) { 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enter an internal frame. 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve registers across notification, this is important for compiled 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stubs that tail call the runtime on deopts passing their parameters in 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // registers. 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushad(); 1306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNotifyStubFailure, save_doubles); 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popad(); 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tear down internal frame. 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(MemOperand(esp, 0)); // Ignore state offset 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); // Return to IC Miss stub, continuation still on stack. 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs); 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) { 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Deoptimizer::BailoutType type) { 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pass deoptimization type to the runtime system. 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); 1330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNotifyDeoptimized); 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tear down internal frame. 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the full codegen state from the stack and untag it. 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Operand(esp, 1 * kPointerSize)); 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(ecx); 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Switch on the state. 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label not_no_registers, not_tos_eax; 1341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)); 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_no_registers, Label::kNear); 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(1 * kPointerSize); // Remove state. 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_no_registers); 1346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(kInterpreterAccumulatorRegister.code(), eax.code()); 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(esp, 2 * kPointerSize)); 1348bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)); 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_tos_eax, Label::kNear); 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(2 * kPointerSize); // Remove state, eax. 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_tos_eax); 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kNoCasesLeft); 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { 1370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argc 1372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : argArray 1374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8] : thisArg 1375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[12] : receiver 1376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Load receiver into edi, argArray into eax (if present), remove all 1379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments from the stack (including the receiver), and push thisArg (if 1380014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // present) instead. 1381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arg_array, no_this_arg; 1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); 1384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, edx); 1385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 1386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_this_arg, Label::kNear); 1388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(esp, eax, times_pointer_size, 0)); 1390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(1)); 1391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &no_arg_array, Label::kNear); 1392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, -kPointerSize)); 1393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arg_array); 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_this_arg); 1396014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 1397014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1398014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 1399014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 1400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 1401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argArray 1405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : receiver 1406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArg 1408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Make sure the receiver is actually callable. 1411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label receiver_not_callable; 1412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear); 1413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); 14143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 14153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsCallable)); 1416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &receiver_not_callable, Label::kNear); 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Tail call with no arguments if argArray is null or undefined. 1419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments; 1420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); 1421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments, 1422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::kNear); 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4a. Apply the receiver to the given argArray (passing undefined for 1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // new.target). 1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); 1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4b. The argArray is either null or undefined, so we tail call without any 1430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments to the receiver. 1431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 1432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Set(eax, 0); 1434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4c. The receiver is not callable, throw an appropriate TypeError. 1438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&receiver_not_callable); 1439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edi); 1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowApplyNonFunction); 1442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) { 1447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Stack Layout: 1448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[0] : Return address 1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[8] : Argument n 1450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[16] : Argument n-1 1451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ... 1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[8 * n] : Argument 1 1453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[8 * (n + 1)] : Receiver (callable to call) 1454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax contains the number of arguments, n, not counting the receiver. 1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Make sure we have at least one argument. 1458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_zero, &done, Label::kNear); 1462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ebx); 1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 1464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ebx); 1465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(eax); 1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Get the callable to call (passed as receiver) from the stack. 1470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Shift arguments and return address one slot down on the stack 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (overwriting the original receiver). Adjust argument count to make 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the original first argument the new receiver. 1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop; 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, eax); 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 1479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0)); 1480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, ecx, times_pointer_size, kPointerSize), ebx); 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(ecx); 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_sign, &loop); // While non-negative (to copy return address). 1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(ebx); // Discard copy of return address. 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(eax); // One fewer argument (first argument is new receiver). 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Call the callable. 1488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ReflectApply(MacroAssembler* masm) { 1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argc 1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : argumentsList 1496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8] : thisArgument 1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[12] : target 1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[16] : receiver 1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Load target into edi (if present), argumentsList into eax (if present), 1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // remove all arguments from the stack (including the receiver), and push 1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // thisArgument (if present) instead. 1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); 1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, edi); 1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(1)); 1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); 1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done, Label::kNear); 1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); 1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(3)); 1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); 1517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 1519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 1521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 1523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argumentsList 1527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArgument 1530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Make sure the target is actually callable. 1533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label target_not_callable; 1534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &target_not_callable, Label::kNear); 1535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); 15363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 15373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsCallable)); 1538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &target_not_callable, Label::kNear); 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3a. Apply the target to the given argumentsList (passing undefined for 1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // new.target). 1542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); 1543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); 1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3b. The target is not callable, throw an appropriate TypeError. 1546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&target_not_callable); 1547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edi); 1549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowApplyNonFunction); 1550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { 1554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argc 1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : new.target (optional) 1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8] : argumentsList 1559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[12] : target 1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[16] : receiver 1561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Load target into edi (if present), argumentsList into eax (if present), 1564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // new.target into edx (if present, otherwise use target), remove all 1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments from the stack (including the receiver), and push thisArgument 1566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (if present) instead. 1567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); 1570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, edi); 1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(1)); 1573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); 1575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done, Label::kNear); 1577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); 1578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(3)); 1579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); 1581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 1585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 1587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argumentsList 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target 1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : receiver (undefined) 1595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Make sure the target is actually a constructor. 1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label target_not_constructor; 1599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &target_not_constructor, Label::kNear); 1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); 16013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 16023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsConstructor)); 1603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &target_not_constructor, Label::kNear); 1604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Make sure the target is actually a constructor. 1606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label new_target_not_constructor; 1607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear); 1608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 16093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 16103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsConstructor)); 1611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &new_target_not_constructor, Label::kNear); 1612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4a. Construct the target with the given new.target and argumentsList. 1614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); 1615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4b. The target is not a constructor, throw an appropriate TypeError. 1617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&target_not_constructor); 1618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edi); 162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ TailCallRuntime(Runtime::kThrowNotConstructor); 1621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4c. The new.target is not a constructor, throw an appropriate TypeError. 1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&new_target_not_constructor); 1625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edx); 162762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ TailCallRuntime(Runtime::kThrowNotConstructor); 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- eax : argc 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[0] : return address 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[4] : last argument 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label generic_array_code; 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the InternalArray function. 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial map for the builtin InternalArray function should be a map. 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Will both indicate a NULL and a Smi. 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ebx, Immediate(kSmiTagMask)); 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction); 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(ebx, MAP_TYPE, ecx); 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction); 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Run the native code for the InternalArray function called as a normal 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // function. 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tail call a stub 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArrayConstructorStub stub(masm->isolate()); 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- eax : argc 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[0] : return address 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[4] : last argument 1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label generic_array_code; 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the Array function. 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); 1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial map for the builtin Array function should be a map. 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Will both indicate a NULL and a Smi. 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ebx, Immediate(kSmiTagMask)); 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(ebx, MAP_TYPE, ecx); 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kUnexpectedInitialMapForArrayFunction); 1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Run the native code for the Array function called as a normal function. 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tail call a stub 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, masm->isolate()->factory()->undefined_value()); 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStub stub(masm->isolate()); 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1689109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { 1690109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 1691109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- eax : number of arguments 169213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // -- edi : function 169313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // -- esi : context 1694109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- esp[0] : return address 1695109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- esp[(argc - n) * 8] : arg[n] (zero-based) 1696109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- esp[(argc + 1) * 8] : receiver 1697109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 1698109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition const cc = (kind == MathMaxMinKind::kMin) ? below : above; 1699109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Heap::RootListIndex const root_index = 1700109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch (kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex 1701109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Heap::kMinusInfinityValueRootIndex; 1702109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch const int reg_sel = (kind == MathMaxMinKind::kMin) ? 1 : 0; 1703109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1704109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the accumulator with the default return value (either -Infinity or 1705109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +Infinity), with the tagged value in edx and the double value in stx_0. 1706109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(edx, root_index); 1707109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset)); 1708109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(ecx, eax); 1709109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1710109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done_loop, loop; 1711109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&loop); 1712109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 1713109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if all parameters done. 1714109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ test(ecx, ecx); 1715109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &done_loop); 1716109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1717109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the next parameter tagged value into ebx. 1718109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0)); 1719109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1720109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the double value of the parameter into stx_1, maybe converting the 172113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // parameter to a number first using the ToNumber builtin if necessary. 1722109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label convert, convert_smi, convert_number, done_convert; 1723109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&convert); 1724109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(ebx, &convert_smi); 1725109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset), 1726109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Heap::kHeapNumberMapRootIndex, &convert_number); 1727109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 172813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Parameter is not a Number, use the ToNumber builtin to convert it. 172913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1730109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(eax); 1731109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(ecx); 1732f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, eax); 1733109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(ecx); 1734109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(edx); 1735109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(eax, ebx); 173613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 1737109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, eax); 1738109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(edx); 1739109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(ecx); 1740f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, eax); 1741f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ecx); 1742f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(eax); 1743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 1744109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore the double accumulator value (stX_0). 1745109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label restore_smi, done_restore; 1746109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(edx, &restore_smi, Label::kNear); 1747109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset)); 1748109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_restore, Label::kNear); 1749109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&restore_smi); 1750109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(edx); 1751109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(edx); 1752109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fild_s(Operand(esp, 0)); 1753109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pop(edx); 1754109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(edx); 1755109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_restore); 1756109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1757109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1758109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&convert); 1759109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&convert_number); 1760109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load another value into stx_1 1761109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fld_d(FieldOperand(ebx, HeapNumber::kValueOffset)); 1762109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fxch(); 1763109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_convert, Label::kNear); 1764109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&convert_smi); 1765109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(ebx); 1766109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(ebx); 1767109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fild_s(Operand(esp, 0)); 1768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ pop(ebx); 1769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fxch(); 1770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(ebx); 1771109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_convert); 1772109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1773109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Perform the actual comparison with the accumulator value on the left hand 1774109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // side (stx_0) and the next parameter value on the right hand side (stx_1). 1775109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label compare_equal, compare_nan, compare_swap, done_compare; 1776109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1777109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Duplicates the 2 float data for FCmp 1778109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fld(1); 1779109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fld(1); 1780109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ FCmp(); 1781109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(parity_even, &compare_nan, Label::kNear); 1782109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(cc, &done_compare, Label::kNear); 1783109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, &compare_equal, Label::kNear); 1784109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1785109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Result is on the right hand side(stx_0). 1786109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&compare_swap); 1787109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fxch(); 1788109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(edx, ebx); 1789109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_compare, Label::kNear); 1790109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1791109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // At least one side is NaN, which means that the result will be NaN too. 1792109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&compare_nan); 1793109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Set the result on the right hand side (stx_0) to nan 1794109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fstp(0); 1795109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(edx, Heap::kNanValueRootIndex); 1796109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset)); 1797109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_compare, Label::kNear); 1798109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1799109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Left and right hand side are equal, check for -0 vs. +0. 1800109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&compare_equal); 1801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check the sign of the value in reg_sel 1802109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fld(reg_sel); 1803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ FXamSign(); 1804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_zero, &compare_swap); 1805109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1806109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_compare); 1807109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // The right result is on the right hand side(stx_0) 1808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // and can remove the useless stx_1 now. 1809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fxch(); 1810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ fstp(0); 1811109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ dec(ecx); 1812109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&loop); 1813109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1814109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_loop); 1816109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PopReturnAddressTo(ecx); 1817109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1818109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PushReturnAddressFrom(ecx); 1819109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(eax, edx); 1820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 1821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// static 1824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_NumberConstructor(MacroAssembler* masm) { 1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- eax : number of arguments 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- edi : constructor function 1828f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[0] : return address 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- esp[(argc + 1) * 4] : receiver 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1834f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1. Load the first argument into ebx. 1835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments; 1836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 1839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2a. Convert the first argument to a number. 1843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(eax); 1846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, eax); 1847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, ebx); 1848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 1849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); // Argc popped to ebx. 1850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 1851f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1852f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1853f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 1855f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 1856f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 1857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 1858f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 1859f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2b. No arguments, return +0 (already in eax). 1862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ret(1 * kPointerSize); 1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments 1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : constructor function 1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new target 1872f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc + 1) * 4] : receiver 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Make sure we operate in the context of the called function. 1879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Store argc in r8. 1882f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ecx, eax); 1883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ecx); 1884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2. Load the first argument into ebx. 1886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments, done; 1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 1890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); 1891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 1893c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(ebx, Smi::kZero); 1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Make sure ebx is a number. 1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done_convert; 1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(ebx, &done_convert); 1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(FieldOperand(ebx, HeapObject::kMapOffset), 1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Heap::kHeapNumberMapRootIndex); 1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done_convert); 1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1905f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1906f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ecx); 1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 190913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 1910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(ebx, eax); 1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 1912f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ecx); 1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_convert); 1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Check if new target and constructor differ. 1918f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label drop_frame_and_ret, done_alloc, new_object; 1919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edx, edi); 1920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &new_object); 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 5. Allocate a JSValue wrapper for the number. 1923f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ AllocateJSValue(eax, edi, ebx, esi, &done_alloc); 1924f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret); 1925f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1926f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&done_alloc); 1927f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); // Restore esi. 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6. Fallback to the runtime to create new object. 1930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&new_object); 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1932f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1933f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ecx); 1934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(ebx); // the first argument 193562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(CodeFactory::FastNewObject(masm->isolate()).code(), 193662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(FieldOperand(eax, JSValue::kValueOffset)); 1938f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ecx); 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1941f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&drop_frame_and_ret); 1942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 1944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(esi); 1945f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ecx); 1946f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ecx, times_pointer_size, kPointerSize)); 1947f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(esi); 1948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 1949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1950f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_StringConstructor(MacroAssembler* masm) { 1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments 1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : constructor function 1957f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 1958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc + 1) * 4] : receiver 1961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1963f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1. Load the first argument into eax. 1964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments; 1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1966f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ebx, eax); // Store argc in ebx. 1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 1969f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(esp, eax, times_pointer_size, 0)); 1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2a. At least one argument, return eax if it's a string, otherwise 1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // dispatch to appropriate conversion. 1974f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label drop_frame_and_ret, to_string, symbol_descriptive_string; 1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(eax, &to_string, Label::kNear); 1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); 1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); 1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above, &to_string, Label::kNear); 1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &symbol_descriptive_string, Label::kNear); 1981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret, Label::kNear); 1982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2b. No arguments, return the empty string (and pop the receiver). 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_arguments); 1986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(eax, Heap::kempty_stringRootIndex); 1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ret(1 * kPointerSize); 1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3a. Convert eax to a string. 1992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&to_string); 1993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1994f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1995f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ebx); 1996f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ebx); 1997f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Call(masm->isolate()->builtins()->ToString(), RelocInfo::CODE_TARGET); 1998f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); 1999f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 2000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2001f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret, Label::kNear); 2002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3b. Convert symbol in eax to a string. 2004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&symbol_descriptive_string); 2005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 2007f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kSymbolDescriptiveString); 2011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2013f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&drop_frame_and_ret); 2014f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2015f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 2016f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 2017f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 2019f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 2020f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2021f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { 2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments 2027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : constructor function 2028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new target 2029f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 2031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc + 1) * 4] : receiver 2033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Make sure we operate in the context of the called function. 2036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ebx, eax); 2039f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2040f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2. Load the first argument into eax. 2041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments, done; 2043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ test(ebx, ebx); 2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 2045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(esp, ebx, times_pointer_size, 0)); 2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 2048f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LoadRoot(eax, Heap::kempty_stringRootIndex); 2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 3. Make sure eax is a string. 2053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label convert, done_convert; 2055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfSmi(eax, &convert, Label::kNear); 2056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); 2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done_convert); 2058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert); 2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 2061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ebx); 2062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ebx); 2063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 2064f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Call(masm->isolate()->builtins()->ToString(), RelocInfo::CODE_TARGET); 2065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 2066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); 2067f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 2068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_convert); 2070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Check if new target and constructor differ. 2073f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label drop_frame_and_ret, done_alloc, new_object; 2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edx, edi); 2075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &new_object); 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2077014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 5. Allocate a JSValue wrapper for the string. 2078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // AllocateJSValue can't handle src == dst register. Reuse esi and restore it 2079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // as needed after the call. 2080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(esi, eax); 2081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ AllocateJSValue(eax, edi, esi, ecx, &done_alloc); 2082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret); 2083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&done_alloc); 2085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Restore eax to the first argument and esi to the context. 2087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, esi); 2088f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6. Fallback to the runtime to create new object. 2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&new_object); 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2094f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 2095f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ebx); 2096f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ebx); 2097f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(eax); // the first argument 209862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Call(CodeFactory::FastNewObject(masm->isolate()).code(), 209962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(FieldOperand(eax, JSValue::kValueOffset)); 2101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); 2102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&drop_frame_and_ret); 2106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 2108f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 2109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 2111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 2112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ebp); 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebp, esp); 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the arguments adaptor context sentinel. 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the function on the stack. 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edi); 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve the number of arguments on the stack. Must preserve eax, 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ebx and ecx because these registers are used when copying the 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // arguments and the receiver. 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(edi, Operand(eax, eax, times_1, kSmiTag)); 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edi); 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Retrieve the number of arguments from the stack. 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave the frame. 2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leave(); 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove caller arguments from the stack. 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(ecx); 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ecx); 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_Apply(MacroAssembler* masm) { 2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argumentsList 2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (checked to be constructor or undefined) 2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address. 2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArgument 2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Create the list of arguments from the array-like argumentsList. 2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 215962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label create_arguments, create_array, create_holey_array, create_runtime, 216062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch done_create; 2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(eax, &create_runtime); 2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the map of argumentsList into ecx. 2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load native context into ebx. 2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, NativeContextOperand()); 2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if argumentsList is an (unmodified) arguments object. 2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ContextOperand(ebx, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); 2171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &create_arguments); 2172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ContextOperand(ebx, Context::STRICT_ARGUMENTS_MAP_INDEX)); 2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &create_arguments); 2174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if argumentsList is a fast JSArray. 2176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_ARRAY_TYPE); 2177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &create_array); 2178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ask the runtime to create the list (actually a FixedArray). 2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&create_runtime); 2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateListFromArrayLike); 2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edi); 2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(eax, FixedArray::kLengthOffset)); 2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done_create); 2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Try to create the list from an arguments object. 2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&create_arguments); 2196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, FieldOperand(eax, JSArgumentsObject::kLengthOffset)); 2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(eax, JSObject::kElementsOffset)); 2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &create_runtime); 2200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, ecx); 2202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done_create); 2203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 220462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // For holey JSArrays we need to check that the array prototype chain 220562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // protector is intact and our prototype is the Array.prototype actually. 220662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&create_holey_array); 220762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 220862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset)); 220962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(ecx, ContextOperand(ebx, Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); 221062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &create_runtime); 221162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadRoot(ecx, Heap::kArrayProtectorRootIndex); 221262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(FieldOperand(ecx, PropertyCell::kValueOffset), 221362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Immediate(Smi::FromInt(Isolate::kProtectorValid))); 221462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &create_runtime); 221562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset)); 221662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ SmiUntag(ebx); 221762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset)); 221862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ jmp(&done_create); 221962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Try to create the list from a JSArray object. 2221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&create_array); 2222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); 2223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ DecodeField<Map::ElementsKindBits>(ecx); 2224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 2225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 2226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FAST_ELEMENTS == 2); 222762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 2228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, Immediate(FAST_HOLEY_SMI_ELEMENTS)); 222962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(equal, &create_holey_array, Label::kNear); 223062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); 223162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(equal, &create_holey_array, Label::kNear); 223262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(above, &create_runtime); 2233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset)); 2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset)); 2236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_create); 2238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check for stack overflow. 2241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check the stack for overflow. We are not trying to catch interruptions 2243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (i.e. debug break and preemption) here, so check the "real stack limit". 2244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 2245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference real_stack_limit = 2246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 2247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand::StaticVariable(real_stack_limit)); 2248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make ecx the space we have left. The stack might already be overflowed 2249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // here which will cause ecx to become negative. 2250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(ecx); 2251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ecx, esp); 2252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sar(ecx, kPointerSizeLog2); 2253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the arguments will overflow the stack. 2254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ebx); 2255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &done, Label::kNear); // Signed comparison. 2256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 2257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 2262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : args (a FixedArray built from argumentsList) 2263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ebx : len (number of elements to push from args) 2264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (checked to be constructor or undefined) 2265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address. 2266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArgument 2267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push arguments onto the stack (thisArgument is already on the stack). 2270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 227162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Save edx/edi to stX0/stX1. 2272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edx); 227362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ push(edi); 2274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ fld_s(MemOperand(esp, 0)); 227562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fld_s(MemOperand(esp, 4)); 227662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(esp, Operand(esp, 2 * kFloatSize)); 2277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(edx); 2279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(ecx, Immediate(0)); 228062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label done, push, loop; 2281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop); 2282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ebx); 2283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done, Label::kNear); 228462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Turn the hole into undefined as we go. 228562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(edi, 228662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FieldOperand(eax, ecx, times_pointer_size, FixedArray::kHeaderSize)); 228762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ CompareRoot(edi, Heap::kTheHoleValueRootIndex); 228862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &push, Label::kNear); 228962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); 229062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&push); 229162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(edi); 2292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(ecx); 2293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&loop); 2294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(edx); 2296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 229762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Restore edx/edi from stX0/stX1. 229862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(esp, Operand(esp, -2 * kFloatSize)); 2299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ fstp_s(MemOperand(esp, 0)); 230062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fstp_s(MemOperand(esp, 4)); 2301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(edx); 230262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ pop(edi); 2303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 2305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch to Call or Construct depending on whether new.target is undefined. 2308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(edx, Heap::kUndefinedValueRootIndex); 2310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 2311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 2312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochnamespace { 2316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Drops top JavaScript frame and an arguments adaptor frame below it (if 2318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// present) preserving all the arguments prepared for current call. 2319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Does nothing if debugger is currently active. 2320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ES6 14.6.3. PrepareForTailCall 2321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// 2322109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Stack structure for the function g() tail calling f(): 2323109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// 2324109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ------- Caller frame: ------- 2325109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2326109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s arg M 2327109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2328109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s arg 1 2329109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s receiver arg 2330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s caller pc 2331109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ------- g()'s frame: ------- 2332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s caller fp <- fp 2333109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s context 2334109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | function pointer: g 2335109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ------------------------- 2336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s arg N 2339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s arg 1 2341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s receiver arg 2342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s caller pc <- sp 2343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ---------------------- 2344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// 2345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid PrepareForTailCall(MacroAssembler* masm, Register args_reg, 2346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch1, Register scratch2, 2347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch3) { 2348109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); 2349109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Comment cmnt(masm, "[ PrepareForTailCall"); 2350109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 23513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Prepare for tail call only if ES2015 tail call elimination is enabled. 2352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done; 23533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ExternalReference is_tail_call_elimination_enabled = 23543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ExternalReference::is_tail_call_elimination_enabled_address( 23553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch masm->isolate()); 23563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ movzx_b(scratch1, 23573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Operand::StaticVariable(is_tail_call_elimination_enabled)); 2358109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(scratch1, Immediate(0)); 23593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(equal, &done, Label::kNear); 2360109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2361109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Drop possible interpreter handler/stub frame. 2362109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 2363109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_interpreter_frame; 23643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset), 2365109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(Smi::FromInt(StackFrame::STUB))); 2366109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &no_interpreter_frame, Label::kNear); 2367109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2368109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_interpreter_frame); 2369109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2370109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2371109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if next frame is an arguments adaptor frame. 23723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register caller_args_count_reg = scratch1; 2373109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_arguments_adaptor, formal_parameter_count_loaded; 2374109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(scratch2, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 23753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ cmp(Operand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset), 2376109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2377109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &no_arguments_adaptor, Label::kNear); 2378109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 23793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Drop current frame and load arguments count from arguments adaptor frame. 2380109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebp, scratch2); 23813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(caller_args_count_reg, 23823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 23833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ SmiUntag(caller_args_count_reg); 2384109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&formal_parameter_count_loaded, Label::kNear); 2385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2386109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_arguments_adaptor); 2387109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load caller's formal parameter count 2388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(scratch1, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 2389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(scratch1, 2390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldOperand(scratch1, JSFunction::kSharedFunctionInfoOffset)); 2391109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov( 23923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch caller_args_count_reg, 2393109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldOperand(scratch1, SharedFunctionInfo::kFormalParameterCountOffset)); 23943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ SmiUntag(caller_args_count_reg); 2395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&formal_parameter_count_loaded); 2397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 23983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ParameterCount callee_args_count(args_reg); 23993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, 24003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch scratch3, ReturnAddressState::kOnStack, 0); 2401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done); 2402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2403109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} // namespace 2404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_CallFunction(MacroAssembler* masm, 2407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ConvertReceiverMode mode, 2408109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TailCallMode tail_call_mode) { 2409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSFunction) 2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(edi); 2414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) 2416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the function is not a "classConstructor". 2417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label class_constructor; 2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), 24203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(SharedFunctionInfo::kClassConstructorBitsWithinByte)); 2421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_zero, &class_constructor); 2422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Enter the context of the function; ToObject has to run in the function 2424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context, and we also need to take the global proxy from the function 2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context in case of conversion. 2426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == 2427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SharedFunctionInfo::kStrictModeByteOffset); 2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We need to convert the receiver for non-native sloppy mode functions. 2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done_convert; 2431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), 24323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate((1 << SharedFunctionInfo::kNativeBitWithinByte) | 24333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); 2434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_zero, &done_convert); 2435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the shared function info. 2439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSFunction) 2440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esi : the function context. 2441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (mode == ConvertReceiverMode::kNullOrUndefined) { 2444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch receiver to global proxy. 2445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalProxy(ecx); 2446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label convert_to_object, convert_receiver; 2448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize)); 2449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(ecx, &convert_to_object, Label::kNear); 2450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx); 2452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above_equal, &done_convert); 2453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (mode != ConvertReceiverMode::kNotNullOrUndefined) { 2454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label convert_global_proxy; 2455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex, 2456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &convert_global_proxy, Label::kNear); 2457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object, 2458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::kNear); 2459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert_global_proxy); 2460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch receiver to global proxy. 2462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalProxy(ecx); 2463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&convert_receiver); 2465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert_to_object); 2467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convert receiver using ToObject. 2469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(bmeurer): Inline the allocation here to avoid building the frame 2470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // in the fast case? (fall back to AllocateInNewSpace?) 2471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiTag(eax); 2473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, ecx); 2476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(esi); 2477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(masm->isolate()->builtins()->ToObject(), 2478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RelocInfo::CODE_TARGET); 2479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Pop(esi); 2480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, eax); 2481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edi); 2482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(eax); 2483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(eax); 2484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert_receiver); 2487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx); 2489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_convert); 2491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the shared function info. 2495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSFunction) 2496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esi : the function context. 2497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (tail_call_mode == TailCallMode::kAllow) { 2500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PrepareForTailCall(masm, eax, ebx, ecx, edx); 2501109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reload shared function info. 2502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2504109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, 2506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 2507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ParameterCount actual(eax); 2509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ParameterCount expected(ebx); 2510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ InvokeFunctionCode(edi, no_reg, expected, actual, JUMP_FUNCTION, 2511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CheckDebugStepCallWrapper()); 2512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The function is a "classConstructor", need to raise an exception. 2513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&class_constructor); 2514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::INTERNAL); 2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edi); 2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowConstructorNonCallableError); 2518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace { 2522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Generate_PushBoundArguments(MacroAssembler* masm) { 2524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (only in case of [[Construct]]) 2527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target (checked to be a JSBoundFunction) 2528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load [[BoundArguments]] into ecx and length of that into ebx. 2531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_bound_arguments; 2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); 2533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 2534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(ebx, ebx); 2536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_bound_arguments); 2537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (only in case of [[Construct]]) 2541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target (checked to be a JSBoundFunction) 2542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ecx : the [[BoundArguments]] (implemented as FixedArray) 2543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ebx : the number of [[BoundArguments]] 2544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reserve stack space for the [[BoundArguments]]. 2547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, Operand(ebx, times_pointer_size, 0)); 2550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(esp, ecx); 2551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check the stack for overflow. We are not trying to catch interruptions 2552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (i.e. debug break and preemption) here, so check the "real stack 2553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // limit". 2554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(esp, ecx, Heap::kRealStackLimitRootIndex); 2555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &done, Label::kNear); // Signed comparison. 2556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore the stack pointer. 2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, 0)); 2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::MANUAL); 2560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ EnterFrame(StackFrame::INTERNAL); 2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Adjust effective number of arguments to include return address. 2567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(eax); 2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Relocate arguments and return address down the stack. 2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop; 2572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Set(ecx, 0); 2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ebx, Operand(esp, ebx, times_pointer_size, 0)); 2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop); 2575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ fld_s(Operand(ebx, ecx, times_pointer_size, 0)); 2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ fstp_s(Operand(esp, ecx, times_pointer_size, 0)); 2577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(ecx); 2578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, eax); 2579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(less, &loop); 2580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Copy [[BoundArguments]] to the stack (below the arguments). 2583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop; 2585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); 2586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 2587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop); 2589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ dec(ebx); 2590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ fld_s( 2591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(ecx, ebx, times_pointer_size, FixedArray::kHeaderSize)); 2592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ fstp_s(Operand(esp, eax, times_pointer_size, 0)); 2593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(eax, Operand(eax, 1)); 2594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &loop); 2595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Adjust effective number of arguments (eax contains the number of 2598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments from the call plus return address plus the number of 2599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // [[BoundArguments]]), so we need to subtract one for the return address. 2600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ dec(eax); 2601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_bound_arguments); 2603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace 2606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm, 2609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TailCallMode tail_call_mode) { 2610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSBoundFunction) 2613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertBoundFunction(edi); 2615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (tail_call_mode == TailCallMode::kAllow) { 2617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PrepareForTailCall(masm, eax, ebx, ecx, edx); 2618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch the receiver to [[BoundThis]]. 2621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(edi, JSBoundFunction::kBoundThisOffset)); 2622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ebx); 2623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the [[BoundArguments]] onto the stack. 2625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_PushBoundArguments(masm); 2626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the [[BoundTargetFunction]] via the Call builtin. 2628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); 2629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand::StaticVariable(ExternalReference( 2630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Builtins::kCall_ReceiverIsAny, masm->isolate()))); 2631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 2632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 2633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode, 2637109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TailCallMode tail_call_mode) { 2638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the target to call (can be any Object). 2641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label non_callable, non_function, non_smi; 2644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &non_callable); 2645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_smi); 2646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2647109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, masm->isolate()->builtins()->CallFunction(mode, tail_call_mode), 2648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); 2650109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, masm->isolate()->builtins()->CallBoundFunction(tail_call_mode), 2651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2653109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if target has a [[Call]] internal method. 26543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 26553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsCallable)); 2656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &non_callable); 2657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_PROXY_TYPE); 2659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &non_function); 2660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // 0. Prepare for tail call if necessary. 2662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (tail_call_mode == TailCallMode::kAllow) { 2663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PrepareForTailCall(masm, eax, ebx, ecx, edx); 2664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2665109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Runtime fallback for Proxy [[Call]]. 2667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 2668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 2670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Increase the arguments size to include the pushed function and the 2671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // existing receiver on the stack. 2672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(eax, Immediate(2)); 2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail-call to the runtime. 2674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpToExternalReference( 2675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference(Runtime::kJSProxyCall, masm->isolate())); 2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Call to something else, which might have a [[Call]] internal method (if 2678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // not we raise an exception). 2679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_function); 2680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Overwrite the original receiver with the (original) target. 2681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); 2682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Let the "call_as_function_delegate" take care of the rest. 2683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, edi); 2684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->CallFunction( 2685109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode), 2686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Call to something that is not callable. 2689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_callable); 2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowCalledNonCallable); 2694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 269762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochstatic void CheckSpreadAndPushToStack(MacroAssembler* masm) { 269862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Free up some registers. 269962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Save edx/edi to stX0/stX1. 270062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ push(edx); 270162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ push(edi); 270262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fld_s(MemOperand(esp, 0)); 270362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fld_s(MemOperand(esp, 4)); 270462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(esp, Operand(esp, 2 * kFloatSize)); 270562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 270662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register argc = eax; 270762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 270862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register scratch = ecx; 270962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register scratch2 = edi; 271062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 271162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register spread = ebx; 271262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register spread_map = edx; 271362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 271462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register spread_len = edx; 271562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 271662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label runtime_call, push_args; 271762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(spread, Operand(esp, kPointerSize)); 271862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ JumpIfSmi(spread, &runtime_call); 271962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); 272062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 272162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check that the spread is an array. 272262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ CmpInstanceType(spread_map, JS_ARRAY_TYPE); 272362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &runtime_call); 272462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 272562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check that we have the original ArrayPrototype. 272662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch, FieldOperand(spread_map, Map::kPrototypeOffset)); 272762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch2, NativeContextOperand()); 272862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(scratch, 272962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ContextOperand(scratch2, Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); 273062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &runtime_call); 273162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 273262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check that the ArrayPrototype hasn't been modified in a way that would 273362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // affect iteration. 273462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadRoot(scratch, Heap::kArrayIteratorProtectorRootIndex); 273562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), 273662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Immediate(Smi::FromInt(Isolate::kProtectorValid))); 273762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &runtime_call); 273862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 273962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check that the map of the initial array iterator hasn't changed. 274062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch2, NativeContextOperand()); 274162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch, 274262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ContextOperand(scratch2, 274362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX)); 274462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 274562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(scratch, 274662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ContextOperand(scratch2, 274762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_MAP_INDEX)); 274862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &runtime_call); 274962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 275062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // For FastPacked kinds, iteration will have the same effect as simply 275162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // accessing each property in order. 275262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label no_protector_check; 275362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch, FieldOperand(spread_map, Map::kBitField2Offset)); 275462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ DecodeField<Map::ElementsKindBits>(scratch); 275562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(scratch, Immediate(FAST_HOLEY_ELEMENTS)); 275662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(above, &runtime_call); 275762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // For non-FastHoley kinds, we can skip the protector check. 275862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(scratch, Immediate(FAST_SMI_ELEMENTS)); 275962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(equal, &no_protector_check); 276062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(scratch, Immediate(FAST_ELEMENTS)); 276162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(equal, &no_protector_check); 276262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check the ArrayProtector cell. 276362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); 276462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), 276562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Immediate(Smi::FromInt(Isolate::kProtectorValid))); 276662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(not_equal, &runtime_call); 276762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 276862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&no_protector_check); 276962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Load the FixedArray backing store, but use the length from the array. 277062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(spread_len, FieldOperand(spread, JSArray::kLengthOffset)); 277162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ SmiUntag(spread_len); 277262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(spread, FieldOperand(spread, JSArray::kElementsOffset)); 277362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ jmp(&push_args); 277462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 277562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&runtime_call); 277662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 277762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Call the builtin for the result of the spread. 277862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 277962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Need to save these on the stack. 278062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Restore edx/edi from stX0/stX1. 278162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(esp, Operand(esp, -2 * kFloatSize)); 278262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fstp_s(MemOperand(esp, 0)); 278362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fstp_s(MemOperand(esp, 4)); 278462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ pop(edx); 278562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ pop(edi); 278662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 278762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(edi); 278862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(edx); 278962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ SmiTag(argc); 279062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(argc); 279162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(spread); 279262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ CallRuntime(Runtime::kSpreadIterableFixed); 279362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(spread, eax); 279462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Pop(argc); 279562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ SmiUntag(argc); 279662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Pop(edx); 279762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Pop(edi); 279862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Free up some registers. 279962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Save edx/edi to stX0/stX1. 280062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ push(edx); 280162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ push(edi); 280262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fld_s(MemOperand(esp, 0)); 280362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fld_s(MemOperand(esp, 4)); 280462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(esp, Operand(esp, 2 * kFloatSize)); 280562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 280662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 280762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 280862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Calculate the new nargs including the result of the spread. 280962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(spread_len, FieldOperand(spread, FixedArray::kLengthOffset)); 281062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ SmiUntag(spread_len); 281162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 281262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&push_args); 281362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // argc += spread_len - 1. Subtract 1 for the spread itself. 281462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(argc, Operand(argc, spread_len, times_1, -1)); 281562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 281662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 281762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check for stack overflow. 281862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 281962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check the stack for overflow. We are not trying to catch interruptions 282062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // (i.e. debug break and preemption) here, so check the "real stack limit". 282162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label done; 282262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); 282362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Make scratch the space we have left. The stack might already be 282462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // overflowed here which will cause scratch to become negative. 282562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ neg(scratch); 282662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ add(scratch, esp); 282762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ sar(scratch, kPointerSizeLog2); 282862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Check if the arguments will overflow the stack. 282962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(scratch, spread_len); 283062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(greater, &done, Label::kNear); // Signed comparison. 283162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 283262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&done); 283362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 283462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 283562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Put the evaluated spread onto the stack as additional arguments. 283662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch { 283762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register return_address = edi; 283862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Pop the return address and spread argument. 283962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ PopReturnAddressTo(return_address); 284062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Pop(scratch); 284162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 284262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Register scratch2 = esi; 284362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Save esi to stX0, edx/edi in stX1/stX2 now. 284462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ push(esi); 284562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fld_s(MemOperand(esp, 0)); 284662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(esp, Operand(esp, 1 * kFloatSize)); 284762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 284862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch, Immediate(0)); 284962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Label done, push, loop; 285062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&loop); 285162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ cmp(scratch, spread_len); 285262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ j(equal, &done, Label::kNear); 285362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ mov(scratch2, FieldOperand(spread, scratch, times_pointer_size, 285462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FixedArray::kHeaderSize)); 285562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ JumpIfNotRoot(scratch2, Heap::kTheHoleValueRootIndex, &push); 285662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadRoot(scratch2, Heap::kUndefinedValueRootIndex); 285762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&push); 285862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Push(scratch2); 285962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ inc(scratch); 286062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ jmp(&loop); 286162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ bind(&done); 286262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ PushReturnAddressFrom(return_address); 286362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 286462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Now Restore esi from stX0, edx/edi from stX1/stX2. 286562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ lea(esp, Operand(esp, -3 * kFloatSize)); 286662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fstp_s(MemOperand(esp, 0)); 286762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fstp_s(MemOperand(esp, 4)); 286862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ fstp_s(MemOperand(esp, 8)); 286962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ pop(esi); 287062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ pop(edx); 287162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ pop(edi); 287262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 287362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 287462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 287562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// static 287662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Builtins::Generate_CallWithSpread(MacroAssembler* masm) { 287762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // ----------- S t a t e ------------- 287862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -- eax : the number of arguments (not including the receiver) 287962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -- edi : the target to call (can be any Object) 288062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // ----------------------------------- 288162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 288262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // CheckSpreadAndPushToStack will push edx to save it. 288362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); 288462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CheckSpreadAndPushToStack(masm); 288562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, 288662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TailCallMode::kDisallow), 288762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::CODE_TARGET); 288862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 288962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructFunction(MacroAssembler* masm) { 2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (checked to be a constructor) 2895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (checked to be a JSFunction) 2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(edi); 2898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Calling convention for function specific ConstructStubs require 2900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ebx to contain either an AllocationSite or undefined. 2901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); 2902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail call to the function-specific construct stub (still in the caller 2904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context at this point). 2905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 2907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 2909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { 2913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (checked to be a constructor) 2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (checked to be a JSBoundFunction) 2917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertBoundFunction(edi); 2919014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2920014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the [[BoundArguments]] onto the stack. 2921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_PushBoundArguments(masm); 2922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch new.target to [[BoundTargetFunction]] if new.target equals target. 2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 2926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edi, edx); 2927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &done, Label::kNear); 2928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); 2929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Construct the [[BoundTargetFunction]] via the Construct builtin. 2933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); 2934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand::StaticVariable( 2935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference(Builtins::kConstruct, masm->isolate()))); 2936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 2938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructProxy(MacroAssembler* masm) { 2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (checked to be a JSProxy) 2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (either the same as the constructor or 2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the JSFunction on which new was invoked initially) 2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call into the Runtime for Proxy [[Construct]]. 2950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 2953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 2954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Include the pushed new_target, constructor and the receiver. 2955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(eax, Immediate(3)); 2956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail-call to the runtime. 2957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpToExternalReference( 2958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); 2959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_Construct(MacroAssembler* masm) { 2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (either the same as the constructor or 2966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the JSFunction on which new was invoked initially) 2967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (can be any Object) 2968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if target is a Smi. 2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label non_constructor; 2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &non_constructor, Label::kNear); 2973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch based on instance type. 2975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->ConstructFunction(), 2977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if target has a [[Construct]] internal method. 29803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 29813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsConstructor)); 2982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &non_constructor, Label::kNear); 2983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Only dispatch to bound functions after checking whether they are 2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // constructors. 2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); 2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), 2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Only dispatch to proxies after checking whether they are constructors. 2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_PROXY_TYPE); 2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->ConstructProxy(), 2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Called Construct on an exotic Object with a [[Construct]] internal method. 2996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Overwrite the original receiver with the (original) target. 2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); 2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Let the "call_as_constructor_delegate" take care of the rest. 3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); 3001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->CallFunction(), 3002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Called Construct on an Object that doesn't have a [[Construct]] internal 3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // method. 3007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_constructor); 3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), 3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 3010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3012bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// static 301362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { 301462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // ----------- S t a t e ------------- 301562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -- eax : the number of arguments (not including the receiver) 301662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -- edx : the new target (either the same as the constructor or 301762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // the JSFunction on which new was invoked initially) 301862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // -- edi : the constructor to call (can be any Object) 301962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // ----------------------------------- 302062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 302162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch CheckSpreadAndPushToStack(masm); 302262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 302362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 302462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 302562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// static 3026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { 3027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 3028bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : requested object size (untagged) 3029bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esp[0] : return address 3030bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 3031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ SmiTag(edx); 3032bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PopReturnAddressTo(ecx); 3033bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(edx); 3034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(ecx); 3035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(esi, Smi::kZero); 3036bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ TailCallRuntime(Runtime::kAllocateInNewSpace); 3037bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 3038bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 3039bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// static 3040bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) { 3041bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 3042bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : requested object size (untagged) 3043bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esp[0] : return address 3044bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 3045bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ SmiTag(edx); 3046bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PopReturnAddressTo(ecx); 3047bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(edx); 3048bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE))); 3049bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(ecx); 3050c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(esi, Smi::kZero); 3051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ TailCallRuntime(Runtime::kAllocateInTargetSpace); 3052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 3053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 305413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// static 3055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_Abort(MacroAssembler* masm) { 3056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------- S t a t e ------------- 3057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- edx : message_id as Smi 3058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esp[0] : return address 3059f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------------------------------- 3060f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 3061f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(edx); 3062f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 3063c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(esi, Smi::kZero); 3064f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ TailCallRuntime(Runtime::kAbort); 306513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 306613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------- S t a t e ------------- 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- eax : actual number of arguments 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ebx : expected number of arguments 3071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new target (passed through to callee) 3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- edi : function (passed through to callee) 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label invoke, dont_adapt_arguments, stack_overflow; 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label enough, too_few; 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, ebx); 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(less, &too_few); 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &dont_adapt_arguments); 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { // Enough parameters: Actual >= expected. 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&enough); 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnterArgumentsAdaptorFrame(masm); 3087f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // edi is used as a scratch register. It should be restored from the frame 3088f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // when needed. 3089f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow); 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy receiver and all expected arguments. 3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int offset = StandardFrameConstants::kCallerSPOffset; 3093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(edi, Operand(ebp, eax, times_4, offset)); 3094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, -1); // account for receiver 3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label copy; 3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(©); 3098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(eax); 3099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(Operand(edi, 0)); 3100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(edi, Immediate(kPointerSize)); 3101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, ebx); 3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(less, ©); 3103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax now contains the expected number of arguments. 3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&invoke); 3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { // Too few parameters: Actual < expected. 3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&too_few); 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnterArgumentsAdaptorFrame(masm); 3110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // edi is used as a scratch register. It should be restored from the frame 3111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // when needed. 3112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow); 3113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Remember expected arguments in ecx. 3115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, ebx); 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy receiver and all actual arguments. 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int offset = StandardFrameConstants::kCallerSPOffset; 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(edi, Operand(ebp, eax, times_4, offset)); 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ebx = expected - actual. 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ebx, eax); 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // eax = -actual - 1 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(eax); 3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(eax, Immediate(1)); 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label copy; 3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(©); 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ inc(eax); 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(edi, 0)); 3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(edi, Immediate(kPointerSize)); 3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(eax, eax); 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, ©); 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill remaining expected arguments with undefined values. 3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fill; 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&fill); 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ inc(eax); 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(masm->isolate()->factory()->undefined_value())); 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, ebx); 3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(less, &fill); 3141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore expected arguments. 3143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, ecx); 3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the entry point. 3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&invoke); 3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore function pointer. 31493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(edi, Operand(ebp, ArgumentsAdaptorFrameConstants::kFunctionOffset)); 3150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax : expected number of arguments 3151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // edx : new target (passed through to callee) 3152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // edi : function (passed through to callee) 3153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 3154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ call(ecx); 3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store offset of return address for deoptimizer. 3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave frame and return. 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LeaveArgumentsAdaptorFrame(masm); 3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ------------------------------------------- 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Dont adapt arguments. 3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ------------------------------------------- 3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&dont_adapt_arguments); 3167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 3168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stack_overflow); 3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame(masm, StackFrame::MANUAL); 3173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver, 3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register function_template_info, 3180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch0, Register scratch1, 3181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* receiver_check_failed) { 3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If there is no signature, return the holder. 3183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(FieldOperand(function_template_info, 3184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FunctionTemplateInfo::kSignatureOffset), 3185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Heap::kUndefinedValueRootIndex); 3186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label receiver_check_passed; 3187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &receiver_check_passed, Label::kNear); 3188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Walk the prototype chain. 3190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); 3191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label prototype_loop_start; 3192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&prototype_loop_start); 3193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the constructor, if any. 3195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ GetMapConstructor(scratch0, scratch0, scratch1); 3196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(scratch1, JS_FUNCTION_TYPE); 3197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label next_prototype; 3198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &next_prototype, Label::kNear); 3199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the constructor's signature. 3201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, 3202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(scratch0, JSFunction::kSharedFunctionInfoOffset)); 3203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, 3204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset)); 3205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Loop through the chain of inheriting function templates. 3207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label function_template_loop; 3208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&function_template_loop); 3209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the signatures match, we have a compatible receiver. 3211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(scratch0, FieldOperand(function_template_info, 3212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FunctionTemplateInfo::kSignatureOffset)); 3213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &receiver_check_passed, Label::kNear); 3214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the current type is not a FunctionTemplateInfo, load the next prototype 3216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // in the chain. 3217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(scratch0, &next_prototype, Label::kNear); 3218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(scratch0, FUNCTION_TEMPLATE_INFO_TYPE, scratch1); 3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &next_prototype, Label::kNear); 3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Otherwise load the parent function template and iterate. 3222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, 3223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(scratch0, FunctionTemplateInfo::kParentTemplateOffset)); 3224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&function_template_loop, Label::kNear); 3225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the next prototype. 3227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&next_prototype); 3228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(receiver, FieldOperand(receiver, HeapObject::kMapOffset)); 3229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ test(FieldOperand(receiver, Map::kBitField3Offset), 3230109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(Map::HasHiddenPrototype::kMask)); 3231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, receiver_check_failed); 3232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(receiver, FieldOperand(receiver, Map::kPrototypeOffset)); 3234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); 3235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Iterate. 3236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&prototype_loop_start, Label::kNear); 3237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&receiver_check_passed); 3239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) { 3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments (not including the receiver) 3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : callee 3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esi : context 3246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 3247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : last argument 3248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ... 3249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[eax * 4] : first argument 3250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(eax + 1) * 4] : receiver 3251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 3252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the FunctionTemplateInfo. 3254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 3255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFunctionDataOffset)); 3256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Do the compatible receiver check. 3258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label receiver_check_failed; 3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand(esp, eax, times_pointer_size, kPCOnStackSize)); 3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CompatibleReceiverCheck(masm, ecx, ebx, edx, eax, &receiver_check_failed); 3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(eax); 3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the callback offset from the FunctionTemplateInfo, and jump to the 3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // beginning of the code. 3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(ebx, FunctionTemplateInfo::kCallCodeOffset)); 3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edx, CallHandlerInfo::kFastHandlerOffset)); 3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(edx); 3269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compatible receiver check failed: pop return address, arguments and 3271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // receiver and throw an Illegal Invocation exception. 3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&receiver_check_failed); 3273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(eax); 3274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ebx); 3275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(eax, Operand(eax, times_pointer_size, 1 * kPointerSize)); 3276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(esp, eax); 3277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ebx); 3278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 3280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowIllegalInvocation); 3281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochstatic void Generate_OnStackReplacementHelper(MacroAssembler* masm, 3285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool has_handler_frame) { 3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Lookup the function in the JavaScript frame. 3287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (has_handler_frame) { 3288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(eax, JavaScriptFrameConstants::kFunctionOffset)); 3290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 3291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 3293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 3295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 3296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pass function as argument. 3297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCompileForOnStackReplacement); 3299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 3302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the code object is null, just return to the caller. 3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, Immediate(0)); 3304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &skip, Label::kNear); 3305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip); 3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3309f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop any potential handler frame that is be sitting on top of the actual 3310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // JavaScript frame. This is the case then OSR is triggered from bytecode. 3311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (has_handler_frame) { 3312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ leave(); 3313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 3314f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load deoptimization data from the code object. 3316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag)); 3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the OSR entrypoint offset from the deoptimization data. 3319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt( 3320f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DeoptimizationInputData::kOsrPcOffsetIndex) - 3321f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch kHeapObjectTag)); 3322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(ebx); 3323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the target address = code_obj + header_size + osr_offset 3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag)); 3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Overwrite the return address on the stack. 3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), eax); 3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // And "return" to the OSR entry point of the function. 3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 3335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Generate_OnStackReplacementHelper(masm, false); 3336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 3337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 3338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { 3339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Generate_OnStackReplacementHelper(masm, true); 3340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 3343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_X87 3347