13ef787dbeca8a5fb1086949cda830dccee07bfbdBen 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_IA32 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/ia32/frames-ia32.h" 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm) 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_Adaptor(MacroAssembler* masm, Address address, 19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExitFrameType exit_frame_type) { 20e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------- S t a t e ------------- 21e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- eax : number of arguments excluding receiver 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target 24e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[0] : return address 25e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[4] : last argument 26e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- ... 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4 * argc] : first argument 28e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // -- esp[4 * (argc +1)] : receiver 29e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // ----------------------------------- 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)); 37e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 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 43e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 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); 51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpToExternalReference(ExternalReference(address, masm->isolate()), 53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch exit_frame_type == BUILTIN_EXIT); 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 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); 86f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch} 87f2e3994fa5148cc3d9946666f0b0596290192b0eBen 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); 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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) { 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax: number of arguments 1203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // -- esi: context 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- edi: constructor function 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx: new target 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Enter a construct frame. 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::CONSTRUCT); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Preserve the incoming parameters on the stack. 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiTag(eax); 131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ push(esi); 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(eax); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver) { 135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Allocate the new receiver object. 136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(edi); 137109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(edx); 138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FastNewObjectStub stub(masm->isolate()); 139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallStub(&stub); 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)); 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 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 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up pointer to last argument. 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy arguments and receiver to the expression stack. 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ecx, eax); 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&entry); 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Operand(ebx, ecx, times_4, 0)); 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ dec(ecx); 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(greater_equal, &loop); 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Call the function. 180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ParameterCount actual(eax); 181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ InvokeFunction(edi, edx, actual, CALL_FUNCTION, 182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch CheckDebugStepCallWrapper()); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store offset of return address for deoptimizer. 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver && !is_api_function) { 1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore context from the frame. 1903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(esi, Operand(ebp, ConstructFrameConstants::kContextOffset)); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver) { 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the result is an object (in the ECMA sense), we should get rid 194109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // of the receiver and use the result. 195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label use_receiver, exit; 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the result is a smi, it is *not* an object in the ECMA sense. 198c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ JumpIfSmi(eax, &use_receiver, Label::kNear); 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the type of the result (stored in its map) is less than 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // FIRST_JS_RECEIVER_TYPE, it is not an object in the ECMA sense. 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, ecx); 203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(above_equal, &exit, Label::kNear); 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Throw away the result of the constructor invocation and use the 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // on-stack receiver as the result. 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&use_receiver); 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Operand(esp, 0)); 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore the arguments count and leave the construct frame. The 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments count is stored below the receiver. 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&exit); 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, 1 * kPointerSize)); 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, 0)); 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave construct frame. 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ES6 9.2.2. Step 13+ 222109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check that the result is not a Smi, indicating that the constructor result 223109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // from a derived class is neither undefined nor an Object. 224109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (check_derived_construct) { 225109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label dont_throw; 226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfNotSmi(eax, &dont_throw); 227109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 228109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallRuntime(Runtime::kThrowDerivedConstructorReturnedNonObject); 230109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&dont_throw); 232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 233109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments from the stack and return. 23569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ecx); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (create_implicit_receiver) { 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 245c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} // namespace 246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 248109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, false, true, false); 249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 252109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, true, false, false); 253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) { 256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, false, false, false); 257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 258109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_JSBuiltinsConstructStubForDerived( 260109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch MacroAssembler* masm) { 261109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Generate_JSConstructStubHelper(masm, false, false, true); 262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) { 265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edi); 267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowConstructedNonConstructable); 268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochenum IsTagged { kEaxIsSmiTagged, kEaxIsUntaggedInt }; 271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Clobbers ecx, edx, edi; preserves all other registers. 273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void Generate_CheckStackOverflow(MacroAssembler* masm, 274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IsTagged eax_is_tagged) { 275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax : the number of items to be pushed to the stack 276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check the stack for overflow. We are not trying to catch 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // limit" is checked. 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label okay; 281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference real_stack_limit = 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand::StaticVariable(real_stack_limit)); 284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make ecx the space we have left. The stack might already be overflowed 285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // here which will cause ecx to become negative. 286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, esp); 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(ecx, edi); 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make edx the space we need for the array when it is unrolled onto the 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // stack. 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, eax); 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int smi_tag = eax_is_tagged == kEaxIsSmiTagged ? kSmiTagSize : 0; 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ shl(edx, kPointerSizeLog2 - smi_tag); 293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the arguments will overflow the stack. 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, edx); 295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &okay); // Signed comparison. 296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Out of stack space. 298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&okay); 301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 302e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_construct) { 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Setup the context (we need to use the caller context from the isolate). 311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference context_address(Isolate::kContextAddress, 312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm->isolate()); 313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, Operand::StaticVariable(context_address)); 314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the previous frame pointer (ebx) to access C arguments 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Operand(ebp, 0)); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the function and the receiver onto the stack. 319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Load the number of arguments and setup pointer to the arguments. 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if we have enough stack space to push all arguments. 327014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Expects argument count in eax. Clobbers ecx, edx, edi. 328014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_CheckStackOverflow(masm, kEaxIsUntaggedInt); 329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Copy arguments to the stack in a loop. 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label loop, entry; 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(ecx, Immediate(0)); 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&entry, Label::kNear); 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&loop); 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv 336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(Operand(edx, 0)); // dereference handle 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ inc(ecx); 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&entry); 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ecx, eax); 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &loop); 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the previous frame pointer (ebx) to access C arguments 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(ebp, 0)); 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the new.target and function from the frame. 346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(ebx, EntryFrameConstants::kNewTargetArgOffset)); 347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke the code. 350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Code> builtin = is_construct 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ? masm->isolate()->builtins()->Construct() 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : masm->isolate()->builtins()->Call(); 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Call(builtin, RelocInfo::CODE_TARGET); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Exit the internal frame. Notice that this also removes the empty. 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // context and the function left on the stack by the code 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // invocation. 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(kPointerSize); // Remove receiver. 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, false); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Generate_JSEntryTrampolineHelper(masm, true); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// static 371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) { 372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- eax : the value to pass to the generator 374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- ebx : the JSGeneratorObject to resume 375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : the resume mode (tagged) 376bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esp[0] : return address 377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 378bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ AssertGeneratorObject(ebx); 379bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 380bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Store input value into generator object. 38113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOrDebugPosOffset), eax); 38213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ RecordWriteField(ebx, JSGeneratorObject::kInputOrDebugPosOffset, eax, ecx, 383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kDontSaveFPRegs); 384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Store resume mode into generator object. 386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(ebx, JSGeneratorObject::kResumeModeOffset), edx); 387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load suspended function and context. 389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset)); 390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); 391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Flood function if we are stepping. 39313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator; 39413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Label stepping_prepared; 39513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ExternalReference last_step_action = 39613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch ExternalReference::debug_last_step_action_address(masm->isolate()); 39713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch STATIC_ASSERT(StepFrame > StepIn); 39813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ cmpb(Operand::StaticVariable(last_step_action), Immediate(StepIn)); 39913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ j(greater_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 440bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Dispatch on the kind of generator object. 441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label old_generator; 442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kFunctionDataOffset)); 444bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ CmpObjectType(ecx, BYTECODE_ARRAY_TYPE, ecx); 445bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(not_equal, &old_generator); 446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // New-style (ignition/turbofan) generator object 448bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(eax); 450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(eax, 452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset)); 453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // We abuse new.target both to indicate that this is a resume call and to 454bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // pass in the generator object. In ordinary calls, new.target is always 455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // undefined because generator functions are non-constructable. 456bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(edx, ebx); 457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(FieldOperand(edi, JSFunction::kCodeEntryOffset)); 458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Old-style (full-codegen) generator object 461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&old_generator); 462bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Enter a new JavaScript frame, and initialize its slots as they were when 464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // the generator was suspended. 465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FrameScope scope(masm, StackFrame::MANUAL); 466bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(eax); // Return address. 467bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(ebp); // Caller's frame pointer. 468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Move(ebp, esp); 469bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(esi); // Callee's context. 470bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(edi); // Callee's JS Function. 471bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 472bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Restore the operand stack. 473bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(eax, FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset)); 474bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch { 475bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label done_loop, loop; 476c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(ecx, Smi::kZero); 477bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&loop); 478bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset)); 479bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(equal, &done_loop, Label::kNear); 480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(FieldOperand(eax, ecx, times_half_pointer_size, 481bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch FixedArray::kHeaderSize)); 482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ add(ecx, Immediate(Smi::FromInt(1))); 483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(&loop); 484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&done_loop); 485bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Reset operand stack so we don't leak. 488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset), 489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(masm->isolate()->factory()->empty_fixed_array())); 490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Resume the generator function at the continuation. 492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); 494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset)); 495bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ SmiUntag(ecx); 496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ lea(edx, FieldOperand(edx, ecx, times_1, Code::kHeaderSize)); 497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset), 498bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))); 499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(eax, ebx); // Continuation expects generator object in eax. 500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(edx); 501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch } 50213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 50313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ bind(&prepare_step_in_if_stepping); 50413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 50513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 50613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(ebx); 50713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edx); 50813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edi); 50913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping); 51013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(edx); 51113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(ebx); 51213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); 51313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 51413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ jmp(&stepping_prepared); 51513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 51613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ bind(&prepare_step_in_suspended_generator); 51713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch { 51813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 51913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(ebx); 52013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edx); 52113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator); 52213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(edx); 52313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(ebx); 52413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); 52513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch } 52613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ jmp(&stepping_prepared); 52713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 52813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 52913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1, 53013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Register scratch2) { 53113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Register args_count = scratch1; 53213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Register return_pc = scratch2; 53313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 53413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Get the arguments + reciever count. 53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(args_count, 53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); 53713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ mov(args_count, 53813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FieldOperand(args_count, BytecodeArray::kParameterSizeOffset)); 53913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 54013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Leave the frame (also dropping the register file). 54113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ leave(); 54213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Drop receiver + arguments. 54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ pop(return_pc); 54513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ add(esp, args_count); 54613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ push(return_pc); 547bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Generate code for entering a JS function with the interpreter. 550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// On entry to the function the receiver and arguments have been pushed on the 551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// stack left to right. The actual argument count matches the formal parameter 552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// count expected by the function. 553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The live registers are: 555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o edi: the JS function object being called 556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o edx: the new target 557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o esi: our context 558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o ebp: the caller's frame pointer 559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// o esp: stack pointer (pointing to return address) 560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 561109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// The function builds an interpreter frame. See InterpreterFrameConstants in 562109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// frames.h for its layout. 563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { 564bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm); 565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the frame (that is done below). 569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame_scope(masm, StackFrame::MANUAL); 570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(ebp); // Caller's frame pointer. 571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebp, esp); 572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(esi); // Callee's context. 573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edi); // Callee's JS function. 574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edx); // Callee's new target. 575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Get the bytecode array from the function object (or from the DebugInfo if 577bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // it is present) and load it into kInterpreterBytecodeArrayRegister. 578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 579109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label load_debug_bytecode_array, bytecode_array_loaded; 580109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset), 581109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(DebugInfo::uninitialized())); 582109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &load_debug_bytecode_array); 583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(kInterpreterBytecodeArrayRegister, 584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset)); 585109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&bytecode_array_loaded); 586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Check whether we should continue to use the interpreter. 588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label switch_to_different_code_kind; 589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Move(ecx, masm->CodeObject()); // Self-reference to this code. 590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ cmp(ecx, FieldOperand(eax, SharedFunctionInfo::kCodeOffset)); 591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ j(not_equal, &switch_to_different_code_kind); 592f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 593f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Increment invocation count for the function. 594f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ EmitLoadTypeFeedbackVector(ecx); 595f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(FieldOperand(ecx, 596f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch TypeFeedbackVector::kInvocationCountIndex * kPointerSize + 597f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch TypeFeedbackVector::kHeaderSize), 598f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Immediate(Smi::FromInt(1))); 599f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Check function data field is actually a BytecodeArray object. 601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code) { 602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(kInterpreterBytecodeArrayRegister); 603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE, 604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch eax); 605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); 606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Push bytecode array. 609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ push(kInterpreterBytecodeArrayRegister); 610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Push Smi tagged initial bytecode array offset. 611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(Immediate(Smi::FromInt(BytecodeArray::kHeaderSize - kHeapObjectTag))); 612109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Allocate the local and temporary register file on the stack. 614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load frame size from the BytecodeArray object. 616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister, 617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BytecodeArray::kFrameSizeOffset)); 618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Do a stack check to ensure we don't go over the limit. 620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label ok; 621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, esp); 622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(ecx, ebx); 623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference stack_limit = 624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, Operand::StaticVariable(stack_limit)); 626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above_equal, &ok); 627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&ok); 629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If ok, push undefined as the initial value for all register file entries. 631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop_header; 632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop_check; 633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value())); 634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&loop_check); 635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_header); 636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(rmcilroy): Consider doing more than one push per loop iteration. 637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(eax); 638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Continue loop if not done. 639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_check); 640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(ebx, Immediate(kPointerSize)); 641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater_equal, &loop_header); 642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 644bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load accumulator, bytecode offset and dispatch table into registers. 645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex); 646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(kInterpreterBytecodeOffsetRegister, 647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag)); 648bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterDispatchTableRegister, 649bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(ExternalReference::interpreter_dispatch_table_address( 650bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()))); 651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch to the first bytecode handler for the function. 653bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, 654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch kInterpreterBytecodeOffsetRegister, times_1, 0)); 655bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, 656bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch times_pointer_size, 0)); 657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ call(ebx); 658bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset()); 659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 660bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // The return value is in eax. 66113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LeaveInterpreterFrame(masm, ebx, ecx); 662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ret(0); 663014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 664bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Load debug copy of the bytecode array. 665bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&load_debug_bytecode_array); 666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register debug_info = kInterpreterBytecodeArrayRegister; 667bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(debug_info, FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset)); 668bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterBytecodeArrayRegister, 669f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FieldOperand(debug_info, DebugInfo::kDebugBytecodeArrayIndex)); 670bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(&bytecode_array_loaded); 671bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 672f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the shared code is no longer this entry trampoline, then the underlying 673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // function has been switched to a different kind of code and we heal the 674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // closure by switching the code entry field over to the new code as well. 675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&switch_to_different_code_kind); 676bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(edx); // Callee's new target. 677bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(edi); // Callee's JS function. 678bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(esi); // Callee's context. 679bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ leave(); // Leave the frame so we can tail call. 680bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 681bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset)); 682bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 683bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(edi, JSFunction::kCodeEntryOffset), ecx); 684bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteCodeEntryField(edi, ecx, ebx); 685bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(ecx); 686bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 688f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, 689f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register scratch1, Register scratch2, 690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label* stack_overflow, 691f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch bool include_receiver = false) { 692f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check the stack for overflow. We are not trying to catch 693f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // interruptions (e.g. debug break and preemption) here, so the "real stack 694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // limit" is checked. 695f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ExternalReference real_stack_limit = 696f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 697f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, Operand::StaticVariable(real_stack_limit)); 698f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Make scratch2 the space we have left. The stack might already be overflowed 699f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // here which will cause scratch2 to become negative. 700f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch2, esp); 701f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(scratch2, scratch1); 702f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Make scratch1 the space we need for the array when it is unrolled onto the 703f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // stack. 704f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, num_args); 705f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (include_receiver) { 706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(scratch1, Immediate(1)); 707f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 708f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ shl(scratch1, kPointerSizeLog2); 709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check if the arguments will overflow the stack. 710f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(scratch2, scratch1); 711f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ j(less_equal, stack_overflow); // Signed comparison. 712f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 713f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void Generate_InterpreterPushArgs(MacroAssembler* masm, 715f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register array_limit, 716f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register start_address) { 717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 718f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- start_address : Pointer to the last argument in the args array. 719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- array_limit : Pointer to one before the first argument in the 720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // args array. 721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop_header, loop_check; 723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&loop_check); 724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_header); 725f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(Operand(start_address, 0)); 726f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(start_address, Immediate(kPointerSize)); 727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop_check); 728f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(start_address, array_limit); 729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &loop_header, Label::kNear); 730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 733109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_InterpreterPushArgsAndCallImpl( 734f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MacroAssembler* masm, TailCallMode tail_call_mode, 735f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch CallableType function_type) { 736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ebx : the address of the first argument to be pushed. Subsequent 739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments should be consecutive above this, in the same order as 740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // they are to be pushed onto the stack. 741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the target to call (can be any Object). 742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 743f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label stack_overflow; 744f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Compute the expected number of arguments. 745f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(ecx, eax); 746f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(ecx, Immediate(1)); // Add one for receiver. 747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Add a stack check before pushing the arguments. We need an extra register 749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // to perform a stack check. So push it onto the stack temporarily. This 750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // might cause stack overflow, but it will be detected by the check. 751f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edi); 752f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, ecx, edx, edi, &stack_overflow); 753f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Pop return address to allow tail-call after pushing arguments. 756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Find the address of the last argument. 759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ shl(ecx, kPointerSizeLog2); 760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(ecx); 761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ecx, ebx); 762f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_InterpreterPushArgs(masm, ecx, ebx); 763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the target. 765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); // Re-push return address. 766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 767f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (function_type == CallableType::kJSFunction) { 768f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, 769f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tail_call_mode), 770f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RelocInfo::CODE_TARGET); 771f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 772f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK_EQ(function_type, CallableType::kAny); 773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, 774f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tail_call_mode), 775f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RelocInfo::CODE_TARGET); 776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 777f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 778f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&stack_overflow); 779f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 780f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pop the temporary registers, so that return address is on top of stack. 781f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 782f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 783f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 784f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 785f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This should be unreachable. 786f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ int3(); 787f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 788f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 790f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace { 791f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 792f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// This function modified start_addr, and only reads the contents of num_args 793f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// register. scratch1 and scratch2 are used as temporary registers. Their 794f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// original values are restored after the use. 795f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Generate_InterpreterPushArgsAndReturnAddress( 796f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MacroAssembler* masm, Register num_args, Register start_addr, 797f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Register scratch1, Register scratch2, bool receiver_in_args, 798f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int num_slots_above_ret_addr, Label* stack_overflow) { 799f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We have to move return address and the temporary registers above it 800f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // before we can copy arguments onto the stack. To achieve this: 801f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 1: Increment the stack pointer by num_args + 1 (for receiver). 802f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 2: Move the return address and values above it to the top of stack. 803f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 3: Copy the arguments into the correct locations. 804f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // current stack =====> required stack layout 805f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | scratch1 | (2) <-- esp(1) 806f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | .... | (2) 807f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | scratch-n | (2) 808f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | return addr | (2) 809f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | | | arg N | (3) 810f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | scratch1 | <-- esp | .... | 811f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | .... | | arg 0 | 812f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | scratch-n | | arg 0 | 813f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // | return addr | | receiver slot | 814f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 815f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Check for stack overflow before we increment the stack pointer. 816f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, num_args, scratch1, scratch2, 817f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch stack_overflow, true); 818f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 819f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Step 1 - Update the stack pointer. scratch1 already contains the required 820f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// increment to the stack. i.e. num_args + 1 stack slots. This is computed in 821f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// the Generate_StackOverflowCheck. 822f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 823f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#ifdef _MSC_VER 824f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // TODO(mythria): Move it to macro assembler. 825f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // In windows, we cannot increment the stack size by more than one page 826f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // (mimimum page size is 4KB) without accessing at least one byte on the 827f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // page. Check this: 828f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx. 829f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const int page_size = 4 * 1024; 830f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label check_offset, update_stack_pointer; 831f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&check_offset); 832f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(scratch1, page_size); 833f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ j(less, &update_stack_pointer); 834f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(esp, Immediate(page_size)); 835f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Just to touch the page, before we increment further. 836f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, 0), Immediate(0)); 837f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(scratch1, Immediate(page_size)); 838f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(&check_offset); 839f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&update_stack_pointer); 840f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif 841f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 842f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(esp, scratch1); 843f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 844f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 2 move return_address and slots above it to the correct locations. 845f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Move from top to bottom, otherwise we may overwrite when num_args = 0 or 1, 846f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // basically when the source and destination overlap. We at least need one 847f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // extra slot for receiver, so no extra checks are required to avoid copy. 848f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch for (int i = 0; i < num_slots_above_ret_addr + 1; i++) { 849f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, 850f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Operand(esp, num_args, times_pointer_size, (i + 1) * kPointerSize)); 851f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, i * kPointerSize), scratch1); 852f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 853f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 854f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Step 3 copy arguments to correct locations. 855f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (receiver_in_args) { 856f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, num_args); 857f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ add(scratch1, Immediate(1)); 858f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 859f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Slot meant for receiver contains return address. Reset it so that 860f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // we will not incorrectly interpret return address as an object. 861f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, num_args, times_pointer_size, 862f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch (num_slots_above_ret_addr + 1) * kPointerSize), 863f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Immediate(0)); 864f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch1, num_args); 865f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 866f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 867f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label loop_header, loop_check; 868f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(&loop_check); 869f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&loop_header); 870f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(scratch2, Operand(start_addr, 0)); 871f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(Operand(esp, scratch1, times_pointer_size, 872f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch num_slots_above_ret_addr * kPointerSize), 873f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch scratch2); 874f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(start_addr, Immediate(kPointerSize)); 875f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ sub(scratch1, Immediate(1)); 876f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&loop_check); 877f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ cmp(scratch1, Immediate(0)); 878f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ j(greater, &loop_header, Label::kNear); 879f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 880f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 881f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} // end anonymous namespace 882f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 884f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Builtins::Generate_InterpreterPushArgsAndConstructImpl( 885f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MacroAssembler* masm, CallableType construct_type) { 886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target 889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor 890f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ebx : allocation site feedback (if available or undefined) 891f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ecx : the address of the first argument to be pushed. Subsequent 892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments should be consecutive above this, in the same order as 893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // they are to be pushed onto the stack. 894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 895f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label stack_overflow; 896f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We need two scratch registers. Push edi and edx onto stack. 897f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edi); 898f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edx); 899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 900f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Push arguments and move return address to the top of stack. 901f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The eax register is readonly. The ecx register will be modified. The edx 902f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // and edi registers will be modified but restored to their original values. 903f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, 904f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 2, &stack_overflow); 905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 906f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Restore edi and edx 907f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 909f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 910f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ AssertUndefinedOrAllocationSite(ebx); 911f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (construct_type == CallableType::kJSFunction) { 912f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Tail call to the function-specific construct stub (still in the caller 913f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // context at this point). 914f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ AssertFunction(edi); 915f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 916f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 917f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 918f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 919f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ jmp(ecx); 920f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } else { 921f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch DCHECK_EQ(construct_type, CallableType::kAny); 922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 923f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Call the constructor with unmodified eax, edi, edx values. 924f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 925f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 927f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&stack_overflow); 928f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 929f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pop the temporary registers, so that return address is on top of stack. 930f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 931f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edi); 932f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 933f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 935f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This should be unreachable. 936f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ int3(); 937f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 938f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 939f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 940f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// static 941f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid Builtins::Generate_InterpreterPushArgsAndConstructArray( 942f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch MacroAssembler* masm) { 943f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // ----------- S t a t e ------------- 944f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- eax : the number of arguments (not including the receiver) 945f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- edx : the target to call checked to be Array function. 946f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ebx : the allocation site feedback 947f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // -- ecx : the address of the first argument to be pushed. Subsequent 948f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // arguments should be consecutive above this, in the same order as 949f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // they are to be pushed onto the stack. 950f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // ----------------------------------- 951f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Label stack_overflow; 952f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // We need two scratch registers. Register edi is available, push edx onto 953f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // stack. 954f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Push(edx); 955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 956f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Push arguments and move return address to the top of stack. 957f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // The eax register is readonly. The ecx register will be modified. The edx 958f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // and edi registers will be modified but restored to their original values. 959f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true, 960f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 1, &stack_overflow); 961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Restore edx. 963f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 964f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 965f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Array constructor expects constructor in edi. It is same as edx here. 966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Move(edi, edx); 967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch ArrayConstructorStub stub(masm->isolate()); 969f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallStub(&stub); 970f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ bind(&stack_overflow); 972f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch { 973f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // Pop the temporary registers, so that return address is on top of stack. 974f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Pop(edx); 975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 978f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // This should be unreachable. 979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ int3(); 980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 983c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochstatic void Generate_InterpreterEnterBytecode(MacroAssembler* masm) { 984bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Set the return address to the correct point in the interpreter entry 985bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // trampoline. 986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Smi* interpreter_entry_return_pc_offset( 987bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()->heap()->interpreter_entry_return_pc_offset()); 988c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch DCHECK_NE(interpreter_entry_return_pc_offset, Smi::kZero); 989bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ LoadHeapObject(ebx, 990bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()->builtins()->InterpreterEntryTrampoline()); 991bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() + 992bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Code::kHeaderSize - kHeapObjectTag)); 993bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(ebx); 994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 995bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Initialize the dispatch table register. 996bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterDispatchTableRegister, 997bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Immediate(ExternalReference::interpreter_dispatch_table_address( 998bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch masm->isolate()))); 999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the bytecode array pointer from the frame. 1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(kInterpreterBytecodeArrayRegister, 1002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); 1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code) { 1005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check function data field is actually a BytecodeArray object. 1006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertNotSmi(kInterpreterBytecodeArrayRegister); 1007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE, 1008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ebx); 1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); 1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the target bytecode offset from the frame. 1013bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(kInterpreterBytecodeOffsetRegister, 1014bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp)); 1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(kInterpreterBytecodeOffsetRegister); 1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch to the target bytecode. 1018bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister, 1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch kInterpreterBytecodeOffsetRegister, times_1, 0)); 1020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx, 1021bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch times_pointer_size, 0)); 1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ebx); 1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1025c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid Builtins::Generate_InterpreterEnterBytecodeAdvance(MacroAssembler* masm) { 1026c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Advance the current bytecode offset stored within the given interpreter 1027c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // stack frame. This simulates what all bytecode handlers do upon completion 1028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // of the underlying operation. 1029c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(ebx, Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp)); 1030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(edx, Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp)); 1031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1032c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 1033c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(kInterpreterAccumulatorRegister); 1035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(ebx); // First argument is the bytecode array. 1036c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Push(edx); // Second argument is the bytecode offset. 1037c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ CallRuntime(Runtime::kInterpreterAdvanceBytecodeOffset); 1038c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(edx, eax); // Result is the new bytecode offset. 1039c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Pop(kInterpreterAccumulatorRegister); 1040c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 1041c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ mov(Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp), edx); 1042c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1043c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Generate_InterpreterEnterBytecode(masm); 1044c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1045c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1046c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { 1047c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Generate_InterpreterEnterBytecode(masm); 1048c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch} 1049c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_CompileLazy(MacroAssembler* masm) { 1051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 1052bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- eax : argument count (preserved for callee) 1053bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : new target (preserved for callee) 1054bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edi : target function (preserved for callee) 1055bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 1056bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // First lookup code, maybe we don't need to compile! 1057bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label gotta_call_runtime, gotta_call_runtime_no_stack; 1058bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label try_shared; 1059bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Label loop_top, loop_bottom; 1060bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1061bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register closure = edi; 1062bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register new_target = edx; 1063bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register argument_count = eax; 1064bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1065bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(argument_count); 1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(new_target); 1067bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(closure); 1068bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1069bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register map = argument_count; 1070bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register index = ebx; 1071bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(map, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset)); 1072bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(map, FieldOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset)); 1073bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(index, FieldOperand(map, FixedArray::kLengthOffset)); 1074bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(index, Immediate(Smi::FromInt(2))); 1075bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(less, &gotta_call_runtime); 1076bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1077bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Find literals. 1078bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // edx : native context 1079bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ebx : length / index 1080bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // eax : optimized code map 1081bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // stack[0] : new target 1082bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // stack[4] : closure 1083bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register native_context = edx; 1084bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(native_context, NativeContextOperand()); 1085bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1086bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&loop_top); 1087bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register temp = edi; 1088bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1089bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Does the native context match? 1090bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(temp, FieldOperand(map, index, times_half_pointer_size, 1091bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SharedFunctionInfo::kOffsetToPreviousContext)); 1092bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset)); 1093bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(temp, native_context); 1094bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(not_equal, &loop_bottom); 1095bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // OSR id set to none? 1096bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(temp, FieldOperand(map, index, times_half_pointer_size, 1097bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SharedFunctionInfo::kOffsetToPreviousOsrAstId)); 1098bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch const int bailout_id = BailoutId::None().ToInt(); 1099bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(temp, Immediate(Smi::FromInt(bailout_id))); 1100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(not_equal, &loop_bottom); 1101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Literals available? 1102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(temp, FieldOperand(map, index, times_half_pointer_size, 1103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SharedFunctionInfo::kOffsetToPreviousLiterals)); 1104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset)); 1105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfSmi(temp, &gotta_call_runtime); 1106bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1107bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Save the literals in the closure. 1108bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ecx, Operand(esp, 0)); 1109bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(ecx, JSFunction::kLiteralsOffset), temp); 1110bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ push(index); 1111bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteField(ecx, JSFunction::kLiteralsOffset, temp, index, 1112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 1113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(index); 1114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Code available? 1116bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Register entry = ecx; 1117bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(map, index, times_half_pointer_size, 1118bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SharedFunctionInfo::kOffsetToPreviousCachedCode)); 1119bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset)); 1120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ JumpIfSmi(entry, &try_shared); 1121bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Found literals and code. Get them into the closure and return. 1123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(closure); 1124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Store code entry in the closure. 1125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ lea(entry, FieldOperand(entry, Code::kHeaderSize)); 1126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry); 1127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteCodeEntryField(closure, entry, eax); 1128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Link the closure into the optimized function list. 1130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ecx : code entry 1131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // edx : native context 1132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // edi : closure 1133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, 1134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST)); 1135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), ebx); 1136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, ebx, eax, 1137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 1138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch const int function_list_offset = 1139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST); 1140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST), 1141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch closure); 1142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Save closure before the write barrier. 1143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, closure); 1144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteContextSlot(native_context, function_list_offset, closure, eax, 1145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch kDontSaveFPRegs); 1146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(closure, ebx); 1147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(new_target); 1148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(argument_count); 1149bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(entry); 1150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1151bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&loop_bottom); 1152bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ sub(index, Immediate(Smi::FromInt(SharedFunctionInfo::kEntryLength))); 1153bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(index, Immediate(Smi::FromInt(1))); 1154bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(greater, &loop_top); 1155bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1156bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // We found neither literals nor code. 1157bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(&gotta_call_runtime); 1158bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1159bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&try_shared); 1160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ pop(closure); 1161bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(new_target); 1162bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(argument_count); 1163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset)); 1164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Is the shared function marked for tier up? 1165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ test_b(FieldOperand(entry, SharedFunctionInfo::kMarkedForTierUpByteOffset), 1166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch Immediate(1 << SharedFunctionInfo::kMarkedForTierUpBitWithinByte)); 1167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ j(not_zero, &gotta_call_runtime_no_stack); 1168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch // Is the full code valid? 1169bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(entry, FieldOperand(entry, SharedFunctionInfo::kCodeOffset)); 1170bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(ebx, FieldOperand(entry, Code::kFlagsOffset)); 1171bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ and_(ebx, Code::KindField::kMask); 1172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ shr(ebx, Code::KindField::kShift); 1173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(ebx, Immediate(Code::BUILTIN)); 1174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ j(equal, &gotta_call_runtime_no_stack); 1175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // Yes, install the full code. 1176bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ lea(entry, FieldOperand(entry, Code::kHeaderSize)); 1177bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry); 1178bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ RecordWriteCodeEntryField(closure, entry, ebx); 1179bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ jmp(entry); 1180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&gotta_call_runtime); 1182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(closure); 1183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(new_target); 1184bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ pop(argument_count); 1185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ bind(&gotta_call_runtime_no_stack); 1186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 1187109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy); 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1190bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_CompileBaseline(MacroAssembler* masm) { 1191bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline); 1192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_CompileOptimized(MacroAssembler* masm) { 1195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateTailCallToReturnedCode(masm, 1196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Runtime::kCompileOptimized_NotConcurrent); 1197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 1198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) { 1200109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileOptimized_Concurrent); 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) { 1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------- S t a t e ------------- 1205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- eax : argument count (preserved for callee) 1206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- edx : new target (preserved for callee) 1207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- edi : target function (preserved for callee) 1208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------------------------------- 1209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label failed; 1210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Preserve argument count for later compare. 1213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ecx, eax); 1214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Push the number of arguments to the callee. 1215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(eax); 1216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(eax); 1217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Push a copy of the target function and the new target. 1218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(edi); 1219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(edx); 1220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // The function. 1222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ push(edi); 1223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Copy arguments from caller (stdlib, foreign, heap). 1224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label args_done; 1225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int j = 0; j < 4; ++j) { 1226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label over; 1227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (j < 3) { 1228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ cmp(ecx, Immediate(j)); 1229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ j(not_equal, &over, Label::kNear); 1230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = j - 1; i >= 0; --i) { 1232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(Operand( 1233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ebp, StandardFrameConstants::kCallerSPOffset + i * kPointerSize)); 1234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0; i < 3 - j; ++i) { 1236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 1237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (j < 3) { 1239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&args_done, Label::kNear); 1240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&over); 1241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&args_done); 1244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Call runtime, on success unwind frame, and parent frame. 1246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CallRuntime(Runtime::kInstantiateAsmJs, 4); 1247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // A smi 0 is returned on failure, an object on success. 1248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfSmi(eax, &failed, Label::kNear); 1249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Drop(2); 1251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Pop(ecx); 1252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ecx); 1253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch scope.GenerateLeaveFrame(); 1254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ebx); 1256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ inc(ecx); 1257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ecx, times_pointer_size, 0)); 1258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ebx); 1259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ ret(0); 1260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&failed); 1262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Restore target function and new target. 1263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ pop(edx); 1264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ pop(edi); 1265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ pop(eax); 1266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(eax); 1267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // On failure, tail call back to regular js. 1269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy); 1270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For now, we are relying on the fact that make_code_young doesn't do any 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // garbage collection which allows us to save/restore the registers without 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // worrying about which of them contain pointers. We also don't build an 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // internal frame to make the code faster, since we shouldn't have to do stack 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // crawls in MakeCodeYoung. This seems a bit fragile. 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Re-execute the code that was patched back to the young age when 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the stub returns. 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(Operand(esp, 0), Immediate(5)); 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushad(); 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(esp, 8 * kPointerSize)); 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(2, ebx); 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 1 * kPointerSize), 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(ExternalReference::isolate_address(masm->isolate()))); 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), eax); 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::get_make_code_young_function(masm->isolate()), 2); 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popad(); 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \ 1298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void Builtins::Generate_Make##C##CodeYoungAgainEvenMarking( \ 1299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MacroAssembler* masm) { \ 1300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); \ 1301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } \ 1302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void Builtins::Generate_Make##C##CodeYoungAgainOddMarking( \ 1303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch MacroAssembler* masm) { \ 1304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); \ 1305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR) 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR 1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that make_code_young doesn't do any garbage collection which allows us to 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // save/restore the registers without worrying about which of them contain 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pointers. 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushad(); 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(esp, 8 * kPointerSize)); 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(eax, Immediate(Assembler::kCallInstructionLength)); 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { // NOLINT 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(2, ebx); 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 1 * kPointerSize), 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(ExternalReference::isolate_address(masm->isolate()))); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), eax); 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::get_mark_code_as_executed_function(masm->isolate()), 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2); 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popad(); 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform prologue operations usually performed by the young code stub. 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); // Pop return address into scratch register. 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(ebp); // Caller's frame pointer. 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebp, esp); 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(esi); // Callee's context. 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edi); // Callee's JS Function. 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); // Push return address after frame prologue. 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Jump to point after the code-age stub. 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) { 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMakeCodeYoungAgainCommon(masm); 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_MarkCodeAsToBeExecutedOnce(MacroAssembler* masm) { 1346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_MarkCodeAsExecutedOnce(masm); 1347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm, 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SaveFPRegsMode save_doubles) { 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enter an internal frame. 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve registers across notification, this is important for compiled 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stubs that tail call the runtime on deopts passing their parameters in 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // registers. 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushad(); 1359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNotifyStubFailure, save_doubles); 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popad(); 13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tear down internal frame. 13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(MemOperand(esp, 0)); // Ignore state offset 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); // Return to IC Miss stub, continuation still on stack. 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) { 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 1377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Deoptimizer::BailoutType type) { 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 1380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Pass deoptimization type to the runtime system. 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); 1383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kNotifyDeoptimized); 1384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tear down internal frame. 13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the full codegen state from the stack and untag it. 1389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ecx, Operand(esp, 1 * kPointerSize)); 1390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ SmiUntag(ecx); 1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Switch on the state. 1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_no_registers, not_tos_eax; 1394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)); 1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, ¬_no_registers, Label::kNear); 1396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ret(1 * kPointerSize); // Remove state. 1397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(¬_no_registers); 1399bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK_EQ(kInterpreterAccumulatorRegister.code(), eax.code()); 1400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(eax, Operand(esp, 2 * kPointerSize)); 1401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)); 1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, ¬_tos_eax, Label::kNear); 1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ret(2 * kPointerSize); // Remove state, eax. 1404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(¬_tos_eax); 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kNoCasesLeft); 1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 1410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { 1423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argc 1425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : argArray 1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8] : thisArg 1428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[12] : receiver 1429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Load receiver into edi, argArray into eax (if present), remove all 1432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments from the stack (including the receiver), and push thisArg (if 1433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // present) instead. 1434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arg_array, no_this_arg; 1436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); 1437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, edx); 1438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 1439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_this_arg, Label::kNear); 1441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(esp, eax, times_pointer_size, 0)); 1443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(1)); 1444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &no_arg_array, Label::kNear); 1445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, -kPointerSize)); 1446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arg_array); 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_this_arg); 1449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 1450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 1452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 1453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 1454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argArray 1458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : receiver 1459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArg 1461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Make sure the receiver is actually callable. 1464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label receiver_not_callable; 1465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &receiver_not_callable, Label::kNear); 1466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); 14673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 14683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsCallable)); 1469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &receiver_not_callable, Label::kNear); 1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Tail call with no arguments if argArray is null or undefined. 1472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments; 1473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfRoot(eax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); 1474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfRoot(eax, Heap::kUndefinedValueRootIndex, &no_arguments, 1475014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::kNear); 1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1477014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4a. Apply the receiver to the given argArray (passing undefined for 1478014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // new.target). 1479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); 1480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); 1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4b. The argArray is either null or undefined, so we tail call without any 1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments to the receiver. 1484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 1485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Set(eax, 0); 1487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1488e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1489e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4c. The receiver is not callable, throw an appropriate TypeError. 1491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&receiver_not_callable); 1492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edi); 1494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowApplyNonFunction); 1495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_FunctionPrototypeCall(MacroAssembler* masm) { 1500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Stack Layout: 1501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[0] : Return address 1502014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[8] : Argument n 1503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[16] : Argument n-1 1504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ... 1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[8 * n] : Argument 1 1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // esp[8 * (n + 1)] : Receiver (callable to call) 1507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax contains the number of arguments, n, not counting the receiver. 1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Make sure we have at least one argument. 1511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_zero, &done, Label::kNear); 1515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ebx); 1516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 1517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ebx); 1518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(eax); 1519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1521589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Get the callable to call (passed as receiver) from the stack. 1523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); 1524402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Shift arguments and return address one slot down on the stack 1526402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // (overwriting the original receiver). Adjust argument count to make 1527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // the original first argument the new receiver. 1528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop; 1530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(ecx, eax); 1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 1532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0)); 1533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, ecx, times_pointer_size, kPointerSize), ebx); 1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ dec(ecx); 1535402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ j(not_sign, &loop); // While non-negative (to copy return address). 1536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(ebx); // Discard copy of return address. 1537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ dec(eax); // One fewer argument (first argument is new receiver). 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Call the callable. 1541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ReflectApply(MacroAssembler* masm) { 1545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argc 1547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : argumentsList 1549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8] : thisArgument 1550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[12] : target 1551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[16] : receiver 1552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Load target into edi (if present), argumentsList into eax (if present), 1555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // remove all arguments from the stack (including the receiver), and push 1556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // thisArgument (if present) instead. 15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); 1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, edi); 1562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(1)); 1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); 1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done, Label::kNear); 1566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); 1567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(3)); 1568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); 1570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 1572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 1574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 1575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 1576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argumentsList 1580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 1581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArgument 1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Make sure the target is actually callable. 1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label target_not_callable; 1587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &target_not_callable, Label::kNear); 1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); 15893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 15903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsCallable)); 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &target_not_callable, Label::kNear); 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3a. Apply the target to the given argumentsList (passing undefined for 1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // new.target). 1595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); 1596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); 1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3b. The target is not callable, throw an appropriate TypeError. 1599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&target_not_callable); 1600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edi); 1602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowApplyNonFunction); 1603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { 1607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1608014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argc 1609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : new.target (optional) 1611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[8] : argumentsList 1612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[12] : target 1613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[16] : receiver 1614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1615589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1616014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Load target into edi (if present), argumentsList into eax (if present), 1617014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // new.target into edx (if present, otherwise use target), remove all 1618014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments from the stack (including the receiver), and push thisArgument 1619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (if present) instead. 1620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 1622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(edi, Heap::kUndefinedValueRootIndex); 1623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, edi); 1625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(1)); 1626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, Operand(esp, eax, times_pointer_size, -0 * kPointerSize)); 1628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done, Label::kNear); 1630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, -1 * kPointerSize)); 1631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Immediate(3)); 1632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done, Label::kNear); 1633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, Operand(esp, eax, times_pointer_size, -2 * kPointerSize)); 1634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 1636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 1638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 1639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argumentsList 1644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target 1645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 1646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : receiver (undefined) 1648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Make sure the target is actually a constructor. 1651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label target_not_constructor; 1652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &target_not_constructor, Label::kNear); 1653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); 16543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 16553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsConstructor)); 1656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &target_not_constructor, Label::kNear); 1657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Make sure the target is actually a constructor. 1659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label new_target_not_constructor; 1660014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edx, &new_target_not_constructor, Label::kNear); 1661014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 16623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 16633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsConstructor)); 1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &new_target_not_constructor, Label::kNear); 1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4a. Construct the target with the given new.target and argumentsList. 1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); 1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4b. The target is not a constructor, throw an appropriate TypeError. 1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&target_not_constructor); 1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edi); 1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowCalledNonCallable); 1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4c. The new.target is not a constructor, throw an appropriate TypeError. 1677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&new_target_not_constructor); 1678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, kPointerSize), edx); 1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowCalledNonCallable); 16813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1682592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 1683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------- S t a t e ------------- 16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- eax : argc 16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- esp[0] : return address 16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- esp[4] : last argument 16893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ----------------------------------- 16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label generic_array_code; 16913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the InternalArray function. 16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); 16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_debug_code) { 16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initial map for the builtin InternalArray function should be a map. 16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 16983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Will both indicate a NULL and a Smi. 16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ test(ebx, Immediate(kSmiTagMask)); 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction); 17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(ebx, MAP_TYPE, ecx); 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction); 17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 17043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 17053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Run the native code for the InternalArray function called as a normal 17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function. 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tail call a stub 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InternalArrayConstructorStub stub(masm->isolate()); 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 17103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : argc 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[0] : return address 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- esp[4] : last argument 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 171825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Label generic_array_code; 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the Array function. 172180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); 1722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, edi); 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_debug_code) { 17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initial map for the builtin Array function should be a map. 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Will both indicate a NULL and a Smi. 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ test(ebx, Immediate(kSmiTagMask)); 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(ebx, MAP_TYPE, ecx); 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kUnexpectedInitialMapForArrayFunction); 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Run the native code for the Array function called as a normal function. 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tail call a stub 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, masm->isolate()->factory()->undefined_value()); 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArrayConstructorStub stub(masm->isolate()); 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallStub(&stub); 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1742109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { 1743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------- S t a t e ------------- 1744109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- eax : number of arguments 174513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // -- edi : function 174613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // -- esi : context 1747109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- esp[0] : return address 1748109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- esp[(argc - n) * 8] : arg[n] (zero-based) 1749109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // -- esp[(argc + 1) * 8] : receiver 1750109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // ----------------------------------- 1751109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Condition const cc = (kind == MathMaxMinKind::kMin) ? below : above; 1752109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Heap::RootListIndex const root_index = 1753109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch (kind == MathMaxMinKind::kMin) ? Heap::kInfinityValueRootIndex 1754109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch : Heap::kMinusInfinityValueRootIndex; 1755109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch XMMRegister const reg = (kind == MathMaxMinKind::kMin) ? xmm1 : xmm0; 1756109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1757109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the accumulator with the default return value (either -Infinity or 1758109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // +Infinity), with the tagged value in edx and the double value in xmm0. 1759109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(edx, root_index); 1760109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 1761109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Move(ecx, eax); 1762109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1763109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done_loop, loop; 1764109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&loop); 1765109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 1766109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if all parameters done. 1767109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ test(ecx, ecx); 1768109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &done_loop); 1769109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1770109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the next parameter tagged value into ebx. 1771109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0)); 1772109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1773109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load the double value of the parameter into xmm1, maybe converting the 177413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // parameter to a number first using the ToNumber builtin if necessary. 1775109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label convert, convert_smi, convert_number, done_convert; 1776109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&convert); 1777109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(ebx, &convert_smi); 1778109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset), 1779109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Heap::kHeapNumberMapRootIndex, &convert_number); 1780109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 178113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch // Parameter is not a Number, use the ToNumber builtin to convert it. 178213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1783109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(eax); 1784109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(ecx); 1785f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, eax); 1786109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(ecx); 1787109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Push(edx); 1788109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(eax, ebx); 178913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 1790109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, eax); 1791109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(edx); 1792109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Pop(ecx); 1793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, eax); 1794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ecx); 1795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(eax); 1796109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 1797109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Restore the double accumulator value (xmm0). 1798109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label restore_smi, done_restore; 1799109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ JumpIfSmi(edx, &restore_smi, Label::kNear); 1800109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 1801109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_restore, Label::kNear); 1802109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&restore_smi); 1803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(edx); 1804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Cvtsi2sd(xmm0, edx); 1805109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(edx); 1806109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_restore); 1807109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&convert); 1810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&convert_number); 1811109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movsd(xmm1, FieldOperand(ebx, HeapNumber::kValueOffset)); 1812109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_convert, Label::kNear); 1813109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&convert_smi); 1814109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiUntag(ebx); 1815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Cvtsi2sd(xmm1, ebx); 1816109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ SmiTag(ebx); 1817109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_convert); 1818109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1819109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Perform the actual comparison with the accumulator value on the left hand 1820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // side (xmm0) and the next parameter value on the right hand side (xmm1). 1821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label compare_equal, compare_nan, compare_swap, done_compare; 1822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ ucomisd(xmm0, xmm1); 1823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(parity_even, &compare_nan, Label::kNear); 1824109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(cc, &done_compare, Label::kNear); 1825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, &compare_equal, Label::kNear); 1826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Result is on the right hand side. 1828109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&compare_swap); 1829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movaps(xmm0, xmm1); 1830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(edx, ebx); 1831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_compare, Label::kNear); 1832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // At least one side is NaN, which means that the result will be NaN too. 1834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&compare_nan); 1835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ LoadRoot(edx, Heap::kNanValueRootIndex); 1836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movsd(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 1837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&done_compare, Label::kNear); 1838109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Left and right hand side are equal, check for -0 vs. +0. 1840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&compare_equal); 184113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Push(edi); // Preserve function in edi. 1842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ movmskpd(edi, reg); 1843109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ test(edi, Immediate(1)); 184413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Pop(edi); 1845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_zero, &compare_swap); 1846109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_compare); 1848109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ dec(ecx); 1849109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&loop); 1850109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 1851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done_loop); 1853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PopReturnAddressTo(ecx); 1854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ PushReturnAddressFrom(ecx); 1856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(eax, edx); 1857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ Ret(); 1858109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 1859109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 1860109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// static 1861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_NumberConstructor(MacroAssembler* masm) { 186280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 186380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- eax : number of arguments 186480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- edi : constructor function 1865f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 186680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- esp[0] : return address 186780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- esp[(argc - n) * 4] : arg[n] (zero-based) 186880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // -- esp[(argc + 1) * 4] : receiver 186980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 187080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1871f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1. Load the first argument into ebx. 1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments; 1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 1876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); 187780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 187880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2a. Convert the first argument to a number. 1880f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1882f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(eax); 1883f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, eax); 1884f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, ebx); 1885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 1886f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); // Argc popped to ebx. 1887f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 1888f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1889f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1890f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1891f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 1892f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 1893f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 1894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 1895f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 1896f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2b. No arguments, return +0 (already in eax). 1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ret(1 * kPointerSize); 1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { 190580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments 1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : constructor function 1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new target 1909f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 1910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc + 1) * 4] : receiver 191380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 191480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Make sure we operate in the context of the called function. 1916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 191780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1918f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Store argc in r8. 1919f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ecx, eax); 1920f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ecx); 1921f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1922f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2. Load the first argument into ebx. 1923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments, done; 1925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 1926014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 1927014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); 1928014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 1929014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 1930c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(ebx, Smi::kZero); 1931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 1932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 193380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Make sure ebx is a number. 1935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done_convert; 1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(ebx, &done_convert); 1938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(FieldOperand(ebx, HeapObject::kMapOffset), 1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Heap::kHeapNumberMapRootIndex); 1940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done_convert); 1941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 1942f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ecx); 1944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 194613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); 1947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(ebx, eax); 1948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 1949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ecx); 1950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_convert); 1952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 195380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Check if new target and constructor differ. 1955f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label drop_frame_and_ret, done_alloc, new_object; 1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edx, edi); 1957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &new_object); 195880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 5. Allocate a JSValue wrapper for the number. 1960f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ AllocateJSValue(eax, edi, ebx, esi, &done_alloc); 1961f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret); 1962f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1963f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&done_alloc); 1964f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); // Restore esi. 196580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6. Fallback to the runtime to create new object. 1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&new_object); 19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 1969f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 1970f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ecx); 1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(ebx); // the first argument 1972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FastNewObjectStub stub(masm->isolate()); 1973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallStub(&stub); 1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(FieldOperand(eax, JSValue::kValueOffset)); 1975f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ecx); 19763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 197780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 1978f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&drop_frame_and_ret); 1979f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 1980f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 1981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(esi); 1982f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ecx); 1983f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ecx, times_pointer_size, kPointerSize)); 1984f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(esi); 1985f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 1986f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1987f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_StringConstructor(MacroAssembler* masm) { 1991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 1992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments 1993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : constructor function 1994f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 1995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 1996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc + 1) * 4] : receiver 1998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 1999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2000f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 1. Load the first argument into eax. 2001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments; 2002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2003f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ebx, eax); // Store argc in ebx. 2004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(eax, eax); 2005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 2006f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(esp, eax, times_pointer_size, 0)); 2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2a. At least one argument, return eax if it's a string, otherwise 2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // dispatch to appropriate conversion. 2011f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label drop_frame_and_ret, to_string, symbol_descriptive_string; 2012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(eax, &to_string, Label::kNear); 2014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); 2015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); 2016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above, &to_string, Label::kNear); 2017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &symbol_descriptive_string, Label::kNear); 2018f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret, Label::kNear); 2019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2b. No arguments, return the empty string (and pop the receiver). 202280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&no_arguments); 2023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(eax, Heap::kempty_stringRootIndex); 2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ret(1 * kPointerSize); 2026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3a. Convert eax to a string. 2029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&to_string); 2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2031f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 2032f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ebx); 2033f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ebx); 2034f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Call(masm->isolate()->builtins()->ToString(), RelocInfo::CODE_TARGET); 2035f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); 2036f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 2037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2038f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret, Label::kNear); 203980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3b. Convert symbol in eax to a string. 2041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&symbol_descriptive_string); 2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 2044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kSymbolDescriptiveString); 2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2050f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&drop_frame_and_ret); 2051f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 2053f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 2054f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2055f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 2056f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 2057f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2058f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { 2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments 2064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : constructor function 2065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new target 2066f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esi : context 2067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 2068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(argc + 1) * 4] : receiver 2070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Make sure we operate in the context of the called function. 2073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2075f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(ebx, eax); 2076f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 2. Load the first argument into eax. 2078014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2079014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_arguments, done; 2080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ test(ebx, ebx); 2081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_arguments, Label::kNear); 2082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(esp, ebx, times_pointer_size, 0)); 2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done, Label::kNear); 2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_arguments); 2085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LoadRoot(eax, Heap::kempty_stringRootIndex); 2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // 3. Make sure eax is a string. 2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label convert, done_convert; 2092f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ JumpIfSmi(eax, &convert, Label::kNear); 2093f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); 2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(below, &done_convert); 2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert); 2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2097f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 2098f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ebx); 2099f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ebx); 2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 2101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch __ Call(masm->isolate()->builtins()->ToString(), RelocInfo::CODE_TARGET); 2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 2103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); 2104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_convert); 2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 4. Check if new target and constructor differ. 2110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Label drop_frame_and_ret, done_alloc, new_object; 2111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edx, edi); 2112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &new_object); 2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 5. Allocate a JSValue wrapper for the string. 2115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // AllocateJSValue can't handle src == dst register. Reuse esi and restore it 2116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // as needed after the call. 2117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(esi, eax); 2118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ AllocateJSValue(eax, edi, esi, ecx, &done_alloc); 2119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ jmp(&drop_frame_and_ret); 2120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 2121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&done_alloc); 2122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Restore eax to the first argument and esi to the context. 2124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, esi); 2125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 6. Fallback to the runtime to create new object. 2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&new_object); 21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 2131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FrameScope scope(masm, StackFrame::MANUAL); 2132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiTag(ebx); 2133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ EnterBuiltinFrame(esi, edi, ebx); 2134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(eax); // the first argument 2135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FastNewObjectStub stub(masm->isolate()); 2136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ CallStub(&stub); 2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(FieldOperand(eax, JSValue::kValueOffset)); 2138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ LeaveBuiltinFrame(esi, edi, ebx); 2139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ SmiUntag(ebx); 21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 214180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ bind(&drop_frame_and_ret); 2143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch { 2144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop all arguments including the receiver. 2145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 2146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); 2147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 2148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Ret(); 2149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 2150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 215180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebp); 21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(ebp, esp); 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the arguments adaptor context sentinel. 2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push the function on the stack. 2160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 2161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Preserve the number of arguments on the stack. Must preserve eax, 2163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ebx and ecx because these registers are used when copying the 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // arguments and the receiver. 216569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1); 2166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lea(edi, Operand(eax, eax, times_1, kSmiTag)); 2167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(edi); 2168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Retrieve the number of arguments from the stack. 2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave the frame. 2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ leave(); 2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments from the stack. 217869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ecx); 2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ecx); 2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_Apply(MacroAssembler* masm) { 2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : argumentsList 2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 2189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (checked to be constructor or undefined) 2190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address. 2191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArgument 2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Create the list of arguments from the array-like argumentsList. 2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label create_arguments, create_array, create_runtime, done_create; 2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(eax, &create_runtime); 2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the map of argumentsList into ecx. 2200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); 2201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load native context into ebx. 2203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, NativeContextOperand()); 2204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if argumentsList is an (unmodified) arguments object. 2206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ContextOperand(ebx, Context::SLOPPY_ARGUMENTS_MAP_INDEX)); 2207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &create_arguments); 2208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ContextOperand(ebx, Context::STRICT_ARGUMENTS_MAP_INDEX)); 2209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &create_arguments); 2210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if argumentsList is a fast JSArray. 2212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_ARRAY_TYPE); 2213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &create_array); 2214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ask the runtime to create the list (actually a FixedArray). 2216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&create_runtime); 2217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 2221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 2222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCreateListFromArrayLike); 2223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edx); 2224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edi); 2225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(eax, FixedArray::kLengthOffset)); 2226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done_create); 2229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Try to create the list from an arguments object. 2231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&create_arguments); 2232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebx, FieldOperand(eax, JSArgumentsObject::kLengthOffset)); 2233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(eax, JSObject::kElementsOffset)); 2234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 2235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &create_runtime); 2236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, ecx); 2238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done_create); 2239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Try to create the list from a JSArray object. 2241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&create_array); 2242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); 2243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ DecodeField<Map::ElementsKindBits>(ecx); 2244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 2245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 2246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(FAST_ELEMENTS == 2); 2247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, Immediate(FAST_ELEMENTS)); 2248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above, &create_runtime); 2249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, Immediate(FAST_HOLEY_SMI_ELEMENTS)); 2250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &create_runtime); 2251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(eax, JSArray::kLengthOffset)); 2252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, FieldOperand(eax, JSArray::kElementsOffset)); 2254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_create); 2256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check for stack overflow. 2259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check the stack for overflow. We are not trying to catch interruptions 2261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (i.e. debug break and preemption) here, so check the "real stack limit". 2262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 2263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference real_stack_limit = 2264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::address_of_real_stack_limit(masm->isolate()); 2265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand::StaticVariable(real_stack_limit)); 2266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make ecx the space we have left. The stack might already be overflowed 2267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // here which will cause ecx to become negative. 2268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ neg(ecx); 2269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ecx, esp); 2270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sar(ecx, kPointerSizeLog2); 2271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if the arguments will overflow the stack. 2272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ebx); 2273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &done, Label::kNear); // Signed comparison. 2274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowStackOverflow); 2275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target 2280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : args (a FixedArray built from argumentsList) 2281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ebx : len (number of elements to push from args) 2282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (checked to be constructor or undefined) 2283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address. 2284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : thisArgument 2285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push arguments onto the stack (thisArgument is already on the stack). 2288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movd(xmm0, edx); 2290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(edx); 2291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(ecx, Immediate(0)); 2292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done, loop; 2293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop); 2294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, ebx); 2295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &done, Label::kNear); 2296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push( 2297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(eax, ecx, times_pointer_size, FixedArray::kHeaderSize)); 2298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(ecx); 2299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&loop); 2300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(edx); 2302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movd(edx, xmm0); 2303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, ebx); 2304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch to Call or Construct depending on whether new.target is undefined. 2307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(edx, Heap::kUndefinedValueRootIndex); 2309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); 2310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 2311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochnamespace { 2315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Drops top JavaScript frame and an arguments adaptor frame below it (if 2317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// present) preserving all the arguments prepared for current call. 2318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Does nothing if debugger is currently active. 2319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ES6 14.6.3. PrepareForTailCall 2320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// 2321109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Stack structure for the function g() tail calling f(): 2322109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// 2323109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ------- Caller frame: ------- 2324109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2325109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s arg M 2326109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2327109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s arg 1 2328109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s receiver arg 2329109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s caller pc 2330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ------- g()'s frame: ------- 2331109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s caller fp <- fp 2332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | g()'s context 2333109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | function pointer: g 2334109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ------------------------- 2335109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s arg N 2338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | ... 2339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s arg 1 2340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s receiver arg 2341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// | f()'s caller pc <- sp 2342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// ---------------------- 2343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// 2344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid PrepareForTailCall(MacroAssembler* masm, Register args_reg, 2345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch1, Register scratch2, 2346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Register scratch3) { 2347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); 2348109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Comment cmnt(masm, "[ PrepareForTailCall"); 2349109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 23503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Prepare for tail call only if ES2015 tail call elimination is enabled. 2351109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label done; 23523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ExternalReference is_tail_call_elimination_enabled = 23533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ExternalReference::is_tail_call_elimination_enabled_address( 23543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch masm->isolate()); 23553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ movzx_b(scratch1, 23563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Operand::StaticVariable(is_tail_call_elimination_enabled)); 2357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ cmp(scratch1, Immediate(0)); 23583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ j(equal, &done, Label::kNear); 2359109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2360109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Drop possible interpreter handler/stub frame. 2361109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch { 2362109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_interpreter_frame; 23633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset), 2364109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(Smi::FromInt(StackFrame::STUB))); 2365109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &no_interpreter_frame, Label::kNear); 2366109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2367109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_interpreter_frame); 2368109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2369109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2370109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if next frame is an arguments adaptor frame. 23713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Register caller_args_count_reg = scratch1; 2372109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Label no_arguments_adaptor, formal_parameter_count_loaded; 2373109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(scratch2, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 23743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ cmp(Operand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset), 2375109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2376109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(not_equal, &no_arguments_adaptor, Label::kNear); 2377109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 23783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch // Drop current frame and load arguments count from arguments adaptor frame. 2379109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(ebp, scratch2); 23803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(caller_args_count_reg, 23813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 23823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ SmiUntag(caller_args_count_reg); 2383109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ jmp(&formal_parameter_count_loaded, Label::kNear); 2384109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2385109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&no_arguments_adaptor); 2386109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Load caller's formal parameter count 2387109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(scratch1, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 2388109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(scratch1, 2389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldOperand(scratch1, JSFunction::kSharedFunctionInfoOffset)); 2390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov( 23913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch caller_args_count_reg, 2392109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch FieldOperand(scratch1, SharedFunctionInfo::kFormalParameterCountOffset)); 23933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ SmiUntag(caller_args_count_reg); 2394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&formal_parameter_count_loaded); 2396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 23973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch ParameterCount callee_args_count(args_reg); 23983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, 23993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch scratch3, ReturnAddressState::kOnStack, 0); 2400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ bind(&done); 2401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} 2402109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch} // namespace 2403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2404014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_CallFunction(MacroAssembler* masm, 2406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ConvertReceiverMode mode, 2407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TailCallMode tail_call_mode) { 2408014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2410014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSFunction) 2411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(edi); 2413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) 2415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the function is not a "classConstructor". 2416014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label class_constructor; 2417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), 24193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(SharedFunctionInfo::kClassConstructorBitsWithinByte)); 2420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_zero, &class_constructor); 2421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Enter the context of the function; ToObject has to run in the function 2423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context, and we also need to take the global proxy from the function 2424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context in case of conversion. 2425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == 2426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SharedFunctionInfo::kStrictModeByteOffset); 2427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We need to convert the receiver for non-native sloppy mode functions. 2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done_convert; 2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), 24313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate((1 << SharedFunctionInfo::kNativeBitWithinByte) | 24323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); 2433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_zero, &done_convert); 2434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the shared function info. 2438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSFunction) 2439014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esi : the function context. 2440014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2442014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (mode == ConvertReceiverMode::kNullOrUndefined) { 2443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch receiver to global proxy. 2444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalProxy(ecx); 2445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label convert_to_object, convert_receiver; 2447014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize)); 2448014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(ecx, &convert_to_object, Label::kNear); 2449014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 2450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx); 2451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(above_equal, &done_convert); 2452014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (mode != ConvertReceiverMode::kNotNullOrUndefined) { 2453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label convert_global_proxy; 2454014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex, 2455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch &convert_global_proxy, Label::kNear); 2456014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object, 2457014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label::kNear); 2458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert_global_proxy); 2459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch receiver to global proxy. 2461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalProxy(ecx); 2462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&convert_receiver); 2464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert_to_object); 2466014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convert receiver using ToObject. 2468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(bmeurer): Inline the allocation here to avoid building the frame 2469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // in the fast case? (fall back to AllocateInNewSpace?) 2470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiTag(eax); 2472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 2473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2474014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, ecx); 2475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(esi); 2476c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Call(masm->isolate()->builtins()->ToObject(), 2477c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch RelocInfo::CODE_TARGET); 2478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Pop(esi); 2479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, eax); 2480014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(edi); 2481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(eax); 2482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(eax); 2483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&convert_receiver); 2486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx); 2488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done_convert); 2490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2493014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the shared function info. 2494014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSFunction) 2495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esi : the function context. 2496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2498109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (tail_call_mode == TailCallMode::kAllow) { 2499109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PrepareForTailCall(masm, eax, ebx, ecx, edx); 2500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Reload shared function info. 2501109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, 2505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 2506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ParameterCount actual(eax); 2508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ParameterCount expected(ebx); 2509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ InvokeFunctionCode(edi, no_reg, expected, actual, JUMP_FUNCTION, 2510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CheckDebugStepCallWrapper()); 2511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The function is a "classConstructor", need to raise an exception. 2512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&class_constructor); 2513014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope frame(masm, StackFrame::INTERNAL); 2515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(edi); 2516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowConstructorNonCallableError); 2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace { 2521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Generate_PushBoundArguments(MacroAssembler* masm) { 2523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (only in case of [[Construct]]) 2526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target (checked to be a JSBoundFunction) 2527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load [[BoundArguments]] into ecx and length of that into ebx. 2530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label no_bound_arguments; 2531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); 2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 2533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ test(ebx, ebx); 2535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &no_bound_arguments); 2536014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2538014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new.target (only in case of [[Construct]]) 2540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : target (checked to be a JSBoundFunction) 2541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ecx : the [[BoundArguments]] (implemented as FixedArray) 2542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ebx : the number of [[BoundArguments]] 2543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reserve stack space for the [[BoundArguments]]. 2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 2548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, Operand(ebx, times_pointer_size, 0)); 2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(esp, ecx); 2550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check the stack for overflow. We are not trying to catch interruptions 2551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // (i.e. debug break and preemption) here, so check the "real stack 2552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // limit". 2553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(esp, ecx, Heap::kRealStackLimitRootIndex); 2554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &done, Label::kNear); // Signed comparison. 2555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore the stack pointer. 2556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, ebx, times_pointer_size, 0)); 2557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::MANUAL); 2559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ EnterFrame(StackFrame::INTERNAL); 2560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Adjust effective number of arguments to include return address. 2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(eax); 2567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Relocate arguments and return address down the stack. 2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop; 2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Set(ecx, 0); 2572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ebx, Operand(esp, ebx, times_pointer_size, 0)); 2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop); 2574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movd(xmm0, Operand(ebx, ecx, times_pointer_size, 0)); 2575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movd(Operand(esp, ecx, times_pointer_size, 0), xmm0); 2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(ecx); 2577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(ecx, eax); 2578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(less, &loop); 2579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Copy [[BoundArguments]] to the stack (below the arguments). 2582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label loop; 2584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); 2585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); 2586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ SmiUntag(ebx); 2587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&loop); 2588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ dec(ebx); 2589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movd(xmm0, FieldOperand(ecx, ebx, times_pointer_size, 2590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FixedArray::kHeaderSize)); 2591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ movd(Operand(esp, eax, times_pointer_size, 0), xmm0); 2592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(eax, Operand(eax, 1)); 2593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(greater, &loop); 2594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Adjust effective number of arguments (eax contains the number of 2597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // arguments from the call plus return address plus the number of 2598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // [[BoundArguments]]), so we need to subtract one for the return address. 2599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ dec(eax); 2600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&no_bound_arguments); 2602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace 2605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm, 2608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TailCallMode tail_call_mode) { 2609014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2611014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the function to call (checked to be a JSBoundFunction) 2612014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2613014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertBoundFunction(edi); 2614014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (tail_call_mode == TailCallMode::kAllow) { 2616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PrepareForTailCall(masm, eax, ebx, ecx, edx); 2617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2618109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2619014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch the receiver to [[BoundThis]]. 2620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(edi, JSBoundFunction::kBoundThisOffset)); 2621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ebx); 2622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2623014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the [[BoundArguments]] onto the stack. 2624014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_PushBoundArguments(masm); 2625014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call the [[BoundTargetFunction]] via the Call builtin. 2627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); 2628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand::StaticVariable(ExternalReference( 2629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Builtins::kCall_ReceiverIsAny, masm->isolate()))); 2630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 2631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 2632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2635109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode, 2636109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch TailCallMode tail_call_mode) { 2637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the target to call (can be any Object). 2640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label non_callable, non_function, non_smi; 2643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &non_callable); 2644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_smi); 2645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2646109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, masm->isolate()->builtins()->CallFunction(mode, tail_call_mode), 2647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); 2649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(equal, masm->isolate()->builtins()->CallBoundFunction(tail_call_mode), 2650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2651109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2652109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // Check if target has a [[Call]] internal method. 26533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 26543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsCallable)); 2655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, &non_callable); 2656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_PROXY_TYPE); 2658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &non_function); 2659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch // 0. Prepare for tail call if necessary. 2661109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (tail_call_mode == TailCallMode::kAllow) { 2662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch PrepareForTailCall(masm, eax, ebx, ecx, edx); 2663109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch } 2664109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 2665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1. Runtime fallback for Proxy [[Call]]. 2666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 2667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 2669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Increase the arguments size to include the pushed function and the 2670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // existing receiver on the stack. 2671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(eax, Immediate(2)); 2672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail-call to the runtime. 2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpToExternalReference( 2674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference(Runtime::kJSProxyCall, masm->isolate())); 2675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2. Call to something else, which might have a [[Call]] internal method (if 2677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // not we raise an exception). 2678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_function); 2679014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Overwrite the original receiver with the (original) target. 2680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); 2681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Let the "call_as_function_delegate" take care of the rest. 2682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, edi); 2683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->CallFunction( 2684109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode), 2685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3. Call to something that is not callable. 2688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_callable); 2689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 2691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowCalledNonCallable); 2693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructFunction(MacroAssembler* masm) { 2698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (checked to be a constructor) 2701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (checked to be a JSFunction) 2702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFunction(edi); 2704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Calling convention for function specific ConstructStubs require 2706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ebx to contain either an AllocationSite or undefined. 2707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); 2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail call to the function-specific construct stub (still in the caller 2710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // context at this point). 2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); 2713014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 2714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 2715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { 2719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (checked to be a constructor) 2722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (checked to be a JSBoundFunction) 2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertBoundFunction(edi); 2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Push the [[BoundArguments]] onto the stack. 2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Generate_PushBoundArguments(masm); 2728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Patch new.target to [[BoundTargetFunction]] if new.target equals target. 2730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done; 2732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edi, edx); 2733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &done, Label::kNear); 2734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); 2735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 2736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Construct the [[BoundTargetFunction]] via the Construct builtin. 2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); 2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand::StaticVariable( 2741014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference(Builtins::kConstruct, masm->isolate()))); 2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); 2743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_ConstructProxy(MacroAssembler* masm) { 2748014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (checked to be a JSProxy) 2751014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (either the same as the constructor or 2752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the JSFunction on which new was invoked initially) 2753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Call into the Runtime for Proxy [[Construct]]. 2756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ecx); 2757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edi); 2758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(edx); 2759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ecx); 2760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Include the pushed new_target, constructor and the receiver. 2761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(eax, Immediate(3)); 2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Tail-call to the runtime. 2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpToExternalReference( 2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); 2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 2768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_Construct(MacroAssembler* masm) { 2769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 2770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : the number of arguments (not including the receiver) 2771014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : the new target (either the same as the constructor or 2772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the JSFunction on which new was invoked initially) 2773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : the constructor to call (can be any Object) 2774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if target is a Smi. 2777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label non_constructor; 2778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(edi, &non_constructor, Label::kNear); 2779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Dispatch based on instance type. 2781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->ConstructFunction(), 2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check if target has a [[Construct]] internal method. 27863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 27873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch Immediate(1 << Map::kIsConstructor)); 2788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(zero, &non_constructor, Label::kNear); 2789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Only dispatch to bound functions after checking whether they are 2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // constructors. 2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); 2793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), 2794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Only dispatch to proxies after checking whether they are constructors. 2797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(ecx, JS_PROXY_TYPE); 2798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, masm->isolate()->builtins()->ConstructProxy(), 2799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Called Construct on an exotic Object with a [[Construct]] internal method. 2802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 2803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Overwrite the original receiver with the (original) target. 2804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); 2805014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Let the "call_as_constructor_delegate" take care of the rest. 2806014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); 2807014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->CallFunction(), 2808014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2809014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Called Construct on an Object that doesn't have a [[Construct]] internal 2812014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // method. 2813014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&non_constructor); 2814014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), 2815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::CODE_TARGET); 2816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2818bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// static 2819bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { 2820bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 2821bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : requested object size (untagged) 2822bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esp[0] : return address 2823bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 2824bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ SmiTag(edx); 2825bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PopReturnAddressTo(ecx); 2826bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(edx); 2827bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(ecx); 2828c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(esi, Smi::kZero); 2829bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ TailCallRuntime(Runtime::kAllocateInNewSpace); 2830bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2831bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 2832bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// static 2833bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) { 2834bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------- S t a t e ------------- 2835bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- edx : requested object size (untagged) 2836bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // -- esp[0] : return address 2837bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // ----------------------------------- 2838bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ SmiTag(edx); 2839bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PopReturnAddressTo(ecx); 2840bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(edx); 2841bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ Push(Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE))); 2842bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ PushReturnAddressFrom(ecx); 2843c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(esi, Smi::kZero); 2844bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch __ TailCallRuntime(Runtime::kAllocateInTargetSpace); 2845bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 2846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 284713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// static 2848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_Abort(MacroAssembler* masm) { 2849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------- S t a t e ------------- 2850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- edx : message_id as Smi 2851f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // -- esp[0] : return address 2852f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // ----------------------------------- 2853f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PopReturnAddressTo(ecx); 2854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ Push(edx); 2855f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ PushReturnAddressFrom(ecx); 2856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch __ Move(esi, Smi::kZero); 2857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ TailCallRuntime(Runtime::kAbort); 285813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 285913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 2861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- eax : actual number of arguments 2863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- ebx : expected number of arguments 2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edx : new target (passed through to callee) 2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- edi : function (passed through to callee) 2866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label invoke, dont_adapt_arguments, stack_overflow; 286944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); 2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label enough, too_few; 28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, ebx); 2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(less, &too_few); 2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 2875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &dont_adapt_arguments); 2876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Enough parameters: Actual >= expected. 2878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&enough); 2879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 2880f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // edi is used as a scratch register. It should be restored from the frame 2881f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // when needed. 2882f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow); 2883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy receiver and all expected arguments. 2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int offset = StandardFrameConstants::kCallerSPOffset; 2886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(edi, Operand(ebp, eax, times_4, offset)); 2887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, -1); // account for receiver 2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ inc(eax); 2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(Operand(edi, 0)); 2893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(edi, Immediate(kPointerSize)); 2894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, ebx); 2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(less, ©); 2896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax now contains the expected number of arguments. 2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&invoke); 2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { // Too few parameters: Actual < expected. 2901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&too_few); 2902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterArgumentsAdaptorFrame(masm); 2903f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // edi is used as a scratch register. It should be restored from the frame 2904f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch // when needed. 2905f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch Generate_StackOverflowCheck(masm, ebx, ecx, edi, &stack_overflow); 2906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Remember expected arguments in ecx. 2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, ebx); 2909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Copy receiver and all actual arguments. 2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int offset = StandardFrameConstants::kCallerSPOffset; 2912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(edi, Operand(ebp, eax, times_4, offset)); 2913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ebx = expected - actual. 29143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(ebx, eax); 2915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // eax = -actual - 1 2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ neg(eax); 29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(1)); 2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label copy; 2920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(©); 2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ inc(eax); 2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Operand(edi, 0)); 29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(edi, Immediate(kPointerSize)); 29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ test(eax, eax); 2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_zero, ©); 2926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill remaining expected arguments with undefined values. 2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fill; 2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fill); 2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ inc(eax); 293144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ push(Immediate(masm->isolate()->factory()->undefined_value())); 29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, ebx); 2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(less, &fill); 2934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restore expected arguments. 2936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, ecx); 2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call the entry point. 2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&invoke); 2941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore function pointer. 29423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch __ mov(edi, Operand(ebp, ArgumentsAdaptorFrameConstants::kFunctionOffset)); 2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // eax : expected number of arguments 2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // edx : new target (passed through to callee) 2945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // edi : function (passed through to callee) 2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 2947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ call(ecx); 29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store offset of return address for deoptimizer. 29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 29515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Leave frame and return. 2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LeaveArgumentsAdaptorFrame(masm); 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Dont adapt arguments. 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ------------------------------------------- 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&dont_adapt_arguments); 2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 2961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ecx); 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stack_overflow); 2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FrameScope frame(masm, StackFrame::MANUAL); 2966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kThrowStackOverflow); 2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ int3(); 2968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver, 2972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register function_template_info, 2973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch0, Register scratch1, 2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* receiver_check_failed) { 2975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If there is no signature, return the holder. 2976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(FieldOperand(function_template_info, 2977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FunctionTemplateInfo::kSignatureOffset), 2978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Heap::kUndefinedValueRootIndex); 2979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label receiver_check_passed; 2980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &receiver_check_passed, Label::kNear); 2981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Walk the prototype chain. 2983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); 2984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label prototype_loop_start; 2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&prototype_loop_start); 2986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the constructor, if any. 2988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ GetMapConstructor(scratch0, scratch0, scratch1); 2989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpInstanceType(scratch1, JS_FUNCTION_TYPE); 2990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label next_prototype; 2991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &next_prototype, Label::kNear); 2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the constructor's signature. 2994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, 2995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(scratch0, JSFunction::kSharedFunctionInfoOffset)); 2996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, 2997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(scratch0, SharedFunctionInfo::kFunctionDataOffset)); 2998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Loop through the chain of inheriting function templates. 3000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label function_template_loop; 3001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&function_template_loop); 3002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the signatures match, we have a compatible receiver. 3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(scratch0, FieldOperand(function_template_info, 3005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FunctionTemplateInfo::kSignatureOffset)); 3006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(equal, &receiver_check_passed, Label::kNear); 3007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the current type is not a FunctionTemplateInfo, load the next prototype 3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // in the chain. 3010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfSmi(scratch0, &next_prototype, Label::kNear); 3011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CmpObjectType(scratch0, FUNCTION_TEMPLATE_INFO_TYPE, scratch1); 3012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ j(not_equal, &next_prototype, Label::kNear); 3013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Otherwise load the parent function template and iterate. 3015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, 3016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FieldOperand(scratch0, FunctionTemplateInfo::kParentTemplateOffset)); 3017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&function_template_loop, Label::kNear); 3018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the next prototype. 3020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&next_prototype); 3021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(receiver, FieldOperand(receiver, HeapObject::kMapOffset)); 3022109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ test(FieldOperand(receiver, Map::kBitField3Offset), 3023109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Immediate(Map::HasHiddenPrototype::kMask)); 3024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch __ j(zero, receiver_check_failed); 3025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 3026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(receiver, FieldOperand(receiver, Map::kPrototypeOffset)); 3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); 3028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Iterate. 3029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&prototype_loop_start, Label::kNear); 3030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&receiver_check_passed); 3032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) { 3035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------- S t a t e ------------- 3036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- eax : number of arguments (not including the receiver) 3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- edi : callee 3038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esi : context 3039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[0] : return address 3040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[4] : last argument 3041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- ... 3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[eax * 4] : first argument 3043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // -- esp[(eax + 1) * 4] : receiver 3044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // ----------------------------------- 3045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load the FunctionTemplateInfo. 3047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 3048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFunctionDataOffset)); 3049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Do the compatible receiver check. 3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label receiver_check_failed; 3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ecx, Operand(esp, eax, times_pointer_size, kPCOnStackSize)); 3053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(eax); 3054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CompatibleReceiverCheck(masm, ecx, ebx, edx, eax, &receiver_check_failed); 3055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(eax); 3056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get the callback offset from the FunctionTemplateInfo, and jump to the 3057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // beginning of the code. 3058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(ebx, FunctionTemplateInfo::kCallCodeOffset)); 3059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, FieldOperand(edx, CallHandlerInfo::kFastHandlerOffset)); 3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(edx); 3062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Compatible receiver check failed: pop return address, arguments and 3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // receiver and throw an Illegal Invocation exception. 3065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&receiver_check_failed); 3066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Pop(eax); 3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PopReturnAddressTo(ebx); 3068014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(eax, Operand(eax, times_pointer_size, 1 * kPointerSize)); 3069014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(esp, eax); 3070014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ PushReturnAddressFrom(ebx); 3071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 3072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 3073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kThrowIllegalInvocation); 3074014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3075014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3076014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3077f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochstatic void Generate_OnStackReplacementHelper(MacroAssembler* masm, 3078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch bool has_handler_frame) { 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Lookup the function in the JavaScript frame. 3080f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (has_handler_frame) { 3081f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 3082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(eax, JavaScriptFrameConstants::kFunctionOffset)); 3083f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else { 3084f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 3086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 30873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 30883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pass function as argument. 30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(eax); 3091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallRuntime(Runtime::kCompileForOnStackReplacement); 30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 3095f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // If the code object is null, just return to the caller. 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, Immediate(0)); 3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &skip, Label::kNear); 3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ret(0); 3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip); 3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // Drop any potential handler frame that is be sitting on top of the actual 3103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // JavaScript frame. This is the case then OSR is triggered from bytecode. 3104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (has_handler_frame) { 3105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch __ leave(); 3106f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 3107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load deoptimization data from the code object. 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag)); 3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the OSR entrypoint offset from the deoptimization data. 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt( 3113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DeoptimizationInputData::kOsrPcOffsetIndex) - 3114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch kHeapObjectTag)); 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(ebx); 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the target address = code_obj + header_size + osr_offset 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag)); 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Overwrite the return address on the stack. 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0), eax); 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // And "return" to the OSR entry point of the function. 3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 3128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Generate_OnStackReplacementHelper(masm, false); 3129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 3130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 3131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { 3132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Generate_OnStackReplacementHelper(masm, true); 3133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 3136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3138f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 3140