1fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Redistribution and use in source and binary forms, with or without 343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// modification, are permitted provided that the following conditions are 443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// met: 543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// * Redistributions of source code must retain the above copyright 743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// notice, this list of conditions and the following disclaimer. 843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// * Redistributions in binary form must reproduce the above 943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// copyright notice, this list of conditions and the following 1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// disclaimer in the documentation and/or other materials provided 1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// with the distribution. 1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// * Neither the name of Google Inc. nor the names of its 1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// contributors may be used to endorse or promote products derived 1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// from this software without specific prior written permission. 1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "v8.h" 2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32 319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com 3244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org#include "codegen.h" 33a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "deoptimizer.h" 34a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "full-codegen.h" 3543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 3671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 { 3771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal { 3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 3943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 4065dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#define __ ACCESS_MASM(masm) 4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 4243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 43b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_Adaptor(MacroAssembler* masm, 44b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org CFunctionId id, 45b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org BuiltinExtraArguments extra_args) { 46b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // ----------- S t a t e ------------- 47b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- eax : number of arguments excluding receiver 48b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- edi : called function (only guaranteed when 49b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // extra_args requires it) 50b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esi : context 51b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[0] : return address 52b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[4] : last argument 53b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- ... 54b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[4 * argc] : first argument (argc == eax) 55b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[4 * (argc +1)] : receiver 56b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // ----------------------------------- 57b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 58b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // Insert extra arguments. 59b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org int num_extra_args = 0; 60b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org if (extra_args == NEEDS_CALLED_FUNCTION) { 61b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org num_extra_args = 1; 62b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org Register scratch = ebx; 63b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org __ pop(scratch); // Save return address. 64b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org __ push(edi); 65b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org __ push(scratch); // Restore return address. 66b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } else { 67b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 68b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } 69b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 70ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org // JumpToExternalReference expects eax to contain the number of arguments 71b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // including the receiver and the extra arguments. 72c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ add(eax, Immediate(num_extra_args + 1)); 73ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ JumpToExternalReference(ExternalReference(id, masm->isolate())); 7443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 7543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 774a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.orgstatic void CallRuntimePassFunction(MacroAssembler* masm, 784a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org Runtime::FunctionId function_id) { 794a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 804a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Push a copy of the function. 814a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ push(edi); 824a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Push call kind information. 834a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ push(ecx); 844a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Function is also the parameter to the runtime call. 854a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ push(edi); 864a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 874a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ CallRuntime(function_id, 1); 884a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Restore call kind information. 894a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ pop(ecx); 904a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Restore receiver. 914a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ pop(edi); 924a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org} 934a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 944a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 95304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.orgstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) { 96304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 97304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset)); 98304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 99304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ jmp(eax); 100304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org} 101304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org 102304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org 103304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.orgvoid Builtins::Generate_InRecompileQueue(MacroAssembler* masm) { 1044a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Checking whether the queued function is ready for install is optional, 1054a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // since we come across interrupts and stack checks elsewhere. However, 1064a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // not checking may delay installing ready functions, and always checking 1074a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // would be quite expensive. A good compromise is to first check against 1084a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // stack limit as a cue for an interrupt signal. 1094a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org Label ok; 1104a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org ExternalReference stack_limit = 1114a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org ExternalReference::address_of_stack_limit(masm->isolate()); 1124a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ cmp(esp, Operand::StaticVariable(stack_limit)); 1134a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ j(above_equal, &ok, Label::kNear); 1144a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 1154a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode); 1164a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Tail call to returned code. 1176e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 1186e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org __ jmp(eax); 1194a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 1204a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ bind(&ok); 1214a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org GenerateTailCallToSharedCode(masm); 1226e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org} 1236e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org 1246e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org 1259259716434187c932704601f700375e53d865de8rossberg@chromium.orgvoid Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) { 1264a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile); 127304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org GenerateTailCallToSharedCode(masm); 128304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org} 129304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org 130304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org 131fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgstatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 132fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org bool is_api_function, 133fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org bool count_constructions) { 134b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // ----------- S t a t e ------------- 135b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // -- eax: number of arguments 136b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // -- edi: constructor function 137b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // ----------------------------------- 138b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 1394a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org // Should never count constructions for api objects. 1404a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org ASSERT(!is_api_function || !count_constructions); 1414a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 1427c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org // Enter a construct frame. 143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 144c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::CONSTRUCT); 14543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Store a smi-tagged arguments count on the stack. 147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiTag(eax); 148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 14943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 150c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the function to invoke on the stack. 151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); 15243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 153c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Try to allocate the object without transitioning into C code. If any of 154c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // the preconditions is not met, the code bails out to the runtime call. 155c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label rt_call, allocated; 156c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (FLAG_inline_new) { 157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label undo_allocation; 15865dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT 159c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference debug_step_in_fp = 160c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::debug_step_in_fp_address(masm->isolate()); 161c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); 162c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &rt_call); 16365dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#endif 16443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 165c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Verified that the constructor is a JSFunction. 166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the initial map and verify that it is in fact a map. 167c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 168c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 169c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Will both indicate a NULL and a Smi 170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfSmi(eax, &rt_call); 171c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 172c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map (if proven valid below) 173c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(eax, MAP_TYPE, ebx); 174c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &rt_call); 175c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 176c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check that the constructor is not constructing a JSFunction (see 177c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // comments in Runtime_NewObject in runtime.cc). In which case the 178c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // initial map's instance type would be JS_FUNCTION_TYPE. 179c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 180c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 181c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpInstanceType(eax, JS_FUNCTION_TYPE); 182c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(equal, &rt_call); 1834a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 184c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (count_constructions) { 185c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label allocate; 186c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Decrease generous allocation count. 187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ dec_b(FieldOperand(ecx, 189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com SharedFunctionInfo::kConstructionCountOffset)); 190c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_zero, &allocate); 1914a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); 1944a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 195c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); // constructor 196c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // The call will replace the stub, so the countdown is only done once. 197c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 1984a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(edi); 200c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(eax); 2014a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&allocate); 203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Now allocate the JSObject on the heap. 206c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 207c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); 209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ shl(edi, kPointerSizeLog2); 210f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); 211c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocated the JSObject, now initialize the fields. 212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object 215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(ebx, JSObject::kMapOffset), eax); 216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Factory* factory = masm->isolate()->factory(); 217c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, factory->empty_fixed_array()); 218c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); 219c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); 220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Set extra fields in the newly allocated object. 221c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 222c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 223c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object 224c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); 225c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, factory->undefined_value()); 2264a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org if (count_constructions) { 227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(esi, 228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lea(esi, 230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize)); 231c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // esi: offset of first field after pre-allocated fields 232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (FLAG_debug_code) { 233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(esi, edi); 234c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Assert(less_equal, 235594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org kUnexpectedNumberOfPreAllocatedPropertyFields); 236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 237c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InitializeFieldsWithFiller(ecx, esi, edx); 2387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ mov(edx, factory->one_pointer_filler_map()); 239c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 240c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InitializeFieldsWithFiller(ecx, edi, edx); 241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Add the object tag to make the JSObject real, so that we can continue 243c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // and jump into the continuation code at any time from now on. Any 244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // failures need to undo the allocation, so that the heap is in a 245c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // consistent state and verifiable. 246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 247c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object 249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ or_(ebx, Immediate(kHeapObjectTag)); 250c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 251c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check if a non-empty properties array is needed. 252c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocate and initialize a FixedArray if it is. 253c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object 256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Calculate the total number of properties described by the map. 257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); 258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(ecx, 259c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ add(edx, ecx); 261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Calculate unused properties past the end of the in-object properties. 262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset)); 263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(edx, ecx); 264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Done if no extra properties are to be allocated. 265c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(zero, &allocated); 266594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(positive, kPropertyAllocationCountFailed); 267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Scale the number of elements by pointer size and add the header for 269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // FixedArrays to the start of the next object calculation from above. 270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object (will be start of FixedArray) 272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edx: number of elements in properties array 273f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate(FixedArray::kHeaderSize, 274f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org times_pointer_size, 275f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org edx, 276f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org REGISTER_VALUE_IS_INT32, 277f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org edi, 278f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org ecx, 279f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org no_reg, 280f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org &undo_allocation, 281f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org RESULT_CONTAINS_TOP); 282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initialize the FixedArray. 284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: FixedArray 286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edx: number of elements 287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ecx: start of next object 288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, factory->fixed_array_map()); 289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map 290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiTag(edx); 291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length 292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initialize the fields to undefined. 294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: FixedArray 296c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ecx: start of next object 297c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { Label loop, entry; 2987979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ mov(edx, factory->undefined_value()); 299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lea(eax, Operand(edi, FixedArray::kHeaderSize)); 300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 301c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(eax, 0), edx); 303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ add(eax, Immediate(kPointerSize)); 304c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ecx); 306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(below, &loop); 3074a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org } 30843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Store the initialized FixedArray into the properties field of 310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // the JSObject 311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: FixedArray 313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag 314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi); 31543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 31643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Continue with JSObject being successfully allocated 318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&allocated); 32043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Undo the setting of the new top so that the heap is verifiable. For 322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // example, the map's unused properties potentially do not match the 323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // allocated objects unused properties. 324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject (previous new top) 325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&undo_allocation); 326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ UndoAllocationInNewSpace(ebx); 327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 32843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocate the new receiver object using the runtime call. 330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&rt_call); 331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Must restore edi (constructor) before calling runtime. 332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand(esp, 0)); 333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: function (constructor) 334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); 335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kNewObject, 1); 336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, eax); // store result in ebx 33743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // New object allocated. 339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: newly allocated object 340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&allocated); 341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Retrieve the function from the stack. 342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(edi); 34343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Retrieve smi-tagged arguments count from the stack. 345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, Operand(esp, 0)); 346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiUntag(eax); 34743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the allocated receiver to the stack. We need two copies 349c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // because we may have to return the original one and the calling 350c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // conventions dictate that the called function pops the receiver. 351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 35343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 354f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up pointer to last argument. 355c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 35643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy arguments and receiver to the expression stack. 358c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label loop, entry; 359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, eax); 360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebx, ecx, times_4, 0)); 363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 364c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ dec(ecx); 365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(greater_equal, &loop); 366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Call the function. 368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (is_api_function) { 369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Handle<Code> code = 371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com masm->isolate()->builtins()->HandleApiCallConstruct(); 372c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount expected(0); 373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET, 374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(eax); 377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(edi, actual, CALL_FUNCTION, 378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com NullCallWrapper(), CALL_AS_METHOD); 379c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 38043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 381967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org // Store offset of return address for deoptimizer. 382967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org if (!is_api_function && !count_constructions) { 383967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 384967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org } 385967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org 386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Restore context from the frame. 387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 38843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the result is an object (in the ECMA sense), we should get rid 390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // of the receiver and use the result; see ECMA-262 section 13.2.2-7 391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // on page 74. 392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label use_receiver, exit; 39343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the result is a smi, it is *not* an object in the ECMA sense. 395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfSmi(eax, &use_receiver); 39643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the type of the result (stored in its map) is less than 398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(above_equal, &exit); 40143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Throw away the result of the constructor invocation and use the 403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // on-stack receiver as the result. 404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&use_receiver); 405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, Operand(esp, 0)); 40643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 407c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Restore the arguments count and leave the construct frame. 408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&exit); 409c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(esp, kPointerSize)); // Get arguments count. 41043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Leave construct frame. 412c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 41343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 41443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Remove caller arguments from the stack and return. 41580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 41643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ pop(ecx); 41743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 41843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(ecx); 4197979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 42043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ ret(0); 42143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 42243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 42343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 4244a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.orgvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { 4254a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org Generate_JSConstructStubHelper(masm, false, true); 4264a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org} 4274a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 4284a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 429b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 4304a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org Generate_JSConstructStubHelper(masm, false, false); 431b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org} 432b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 433b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 434b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 4354a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org Generate_JSConstructStubHelper(masm, true, false); 436b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org} 437b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 438b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 43943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 44043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen bool is_construct) { 4411510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 4421510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Clear the context before we push it when entering the internal frame. 4445d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org __ Set(esi, Immediate(0)); 44543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 44843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the previous frame pointer (ebx) to access C arguments 450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(ebp, 0)); 45143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the function from the frame and setup the context. 453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); 45543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 456c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the function and the receiver onto the stack. 457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ecx); 458c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); 45943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 460c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the number of arguments and setup pointer to the arguments. 461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); 462c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); 46343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 464c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy arguments to the stack in a loop. 465c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label loop, entry; 466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Set(ecx, Immediate(0)); 467c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 468c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv 470c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(edx, 0)); // dereference handle 471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ inc(ecx); 472c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 473c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ecx, eax); 474c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &loop); 475c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 476c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the function from the stack and call it. 477c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // kPointerSize for the receiver. 478c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand(esp, eax, times_4, kPointerSize)); 479c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Invoke the code. 481c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (is_construct) { 482a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org // No type feedback cell is available 483a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org Handle<Object> undefined_sentinel( 484a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org masm->isolate()->heap()->undefined_value(), masm->isolate()); 485a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org __ mov(ebx, Immediate(undefined_sentinel)); 486fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 487fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ CallStub(&stub); 488c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(eax); 490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(edi, actual, CALL_FUNCTION, 491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com NullCallWrapper(), CALL_AS_METHOD); 492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 49343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Exit the internal frame. Notice that this also removes the empty. 495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // context and the function left on the stack by the code 496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // invocation. 49743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ ret(kPointerSize); // Remove receiver. 49943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 50043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 50143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 50243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 50343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Generate_JSEntryTrampolineHelper(masm, false); 50443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 50543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 50643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 50743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 50843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Generate_JSEntryTrampolineHelper(masm, true); 50943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 51043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 51143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 512ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.orgvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) { 5134a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kLazyCompile); 514ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org // Do a tail-call of the compiled function. 51540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(eax); 517ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org} 518ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org 519ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org 520a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) { 5214a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kLazyRecompile); 522a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Do a tail-call of the compiled function. 52340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(eax); 525a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 526a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 527a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 528e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { 529e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // For now, we are relying on the fact that make_code_young doesn't do any 530e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // garbage collection which allows us to save/restore the registers without 531e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // worrying about which of them contain pointers. We also don't build an 532e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // internal frame to make the code faster, since we shouldn't have to do stack 533e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // crawls in MakeCodeYoung. This seems a bit fragile. 534e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 535e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // Re-execute the code that was patched back to the young age when 536e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // the stub returns. 537e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ sub(Operand(esp, 0), Immediate(5)); 538e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ pushad(); 539e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ mov(eax, Operand(esp, 8 * kPointerSize)); 540e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org { 541e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 542528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ PrepareCallCFunction(2, ebx); 543528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), 544528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org Immediate(ExternalReference::isolate_address(masm->isolate()))); 545e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ mov(Operand(esp, 0), eax); 546e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ CallCFunction( 547528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ExternalReference::get_make_code_young_function(masm->isolate()), 2); 548e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org } 549e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ popad(); 550e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ ret(0); 551e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org} 552e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 553e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \ 554e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainEvenMarking( \ 555e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org MacroAssembler* masm) { \ 556e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 557e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org} \ 558e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainOddMarking( \ 559e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org MacroAssembler* masm) { \ 560e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 561e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org} 562e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR) 563e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR 564e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 565e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 566c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { 567c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact 568c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // that make_code_young doesn't do any garbage collection which allows us to 569c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // save/restore the registers without worrying about which of them contain 570c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // pointers. 571c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ pushad(); 572c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(eax, Operand(esp, 8 * kPointerSize)); 573c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ sub(eax, Immediate(Assembler::kCallInstructionLength)); 574c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org { // NOLINT 575c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 576c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ PrepareCallCFunction(2, ebx); 577c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(Operand(esp, 1 * kPointerSize), 578c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org Immediate(ExternalReference::isolate_address(masm->isolate()))); 579c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(Operand(esp, 0), eax); 580c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ CallCFunction( 581c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org ExternalReference::get_mark_code_as_executed_function(masm->isolate()), 582c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 2); 583c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org } 584c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ popad(); 585c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 586c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // Perform prologue operations usually performed by the young code stub. 587c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ pop(eax); // Pop return address into scratch register. 588c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(ebp); // Caller's frame pointer. 589c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(ebp, esp); 590c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(esi); // Callee's context. 591c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(edi); // Callee's JS Function. 592c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(eax); // Push return address after frame prologue. 593c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 594c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // Jump to point after the code-age stub. 595c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ ret(0); 596c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org} 597c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 598c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 599c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) { 600c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org GenerateMakeCodeYoungAgainCommon(masm); 601c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org} 602c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 603c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 604f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm, 605f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SaveFPRegsMode save_doubles) { 606a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Enter an internal frame. 607a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org { 608a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 609a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 610a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Preserve registers across notification, this is important for compiled 611a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // stubs that tail call the runtime on deopts passing their parameters in 612a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // registers. 613a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ pushad(); 614f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles); 615a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ popad(); 616a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Tear down internal frame. 617a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 618a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 619a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ pop(MemOperand(esp, 0)); // Ignore state offset 620a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ ret(0); // Return to IC Miss stub, continuation still on stack. 621a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org} 622a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 623a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 624f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { 625f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs); 626f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 627f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 628f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 629f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) { 630ecfa363c53ab5e5f01fb0645fabd2c060c967385ulan@chromium.org if (Serializer::enabled()) { 631ecfa363c53ab5e5f01fb0645fabd2c060c967385ulan@chromium.org PlatformFeatureScope sse2(SSE2); 632ecfa363c53ab5e5f01fb0645fabd2c060c967385ulan@chromium.org Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 633ecfa363c53ab5e5f01fb0645fabd2c060c967385ulan@chromium.org } else { 634ecfa363c53ab5e5f01fb0645fabd2c060c967385ulan@chromium.org Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 635ecfa363c53ab5e5f01fb0645fabd2c060c967385ulan@chromium.org } 636f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 637f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 638f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 639a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 640a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Deoptimizer::BailoutType type) { 641c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 642c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 643a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 644659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org // Pass deoptimization type to the runtime system. 645c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); 646c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 647a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Tear down internal frame. 649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 650a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 651a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Get the full codegen state from the stack and untag it. 652a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(ecx, Operand(esp, 1 * kPointerSize)); 653a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ SmiUntag(ecx); 654a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 655a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Switch on the state. 65683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Label not_no_registers, not_tos_eax; 657a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ cmp(ecx, FullCodeGenerator::NO_REGISTERS); 65883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ j(not_equal, ¬_no_registers, Label::kNear); 659a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ret(1 * kPointerSize); // Remove state. 660a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 661a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(¬_no_registers); 662a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(eax, Operand(esp, 2 * kPointerSize)); 663a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ cmp(ecx, FullCodeGenerator::TOS_REG); 66483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ j(not_equal, ¬_tos_eax, Label::kNear); 665a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ret(2 * kPointerSize); // Remove state, eax. 666a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 667a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(¬_tos_eax); 668594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kNoCasesLeft); 669a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 670a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 671a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 672a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 673a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 674a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 675a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 676a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 677aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.orgvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 678aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 679aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org} 680aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org 681aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org 682a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 683a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 684a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 685a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 686a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 687b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 6887979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Factory* factory = masm->isolate()->factory(); 6897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org 690b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // 1. Make sure we have at least one argument. 691b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org { Label done; 692c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(eax, eax); 6937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ j(not_zero, &done); 694b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ pop(ebx); 6957979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ push(Immediate(factory->undefined_value())); 696b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ push(ebx); 697b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ inc(eax); 698b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&done); 699b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 700b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7015c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 2. Get the function to call (passed as receiver) from the stack, check 7025c838251403b0be9a882540f1922577abba4c872ager@chromium.org // if it is a function. 70334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org Label slow, non_function; 7045c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 1 ~ return address. 7055c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); 7067b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(edi, &non_function); 7075c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 70834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(not_equal, &slow); 709b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 710b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7115c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 3a. Patch the first argument if necessary when calling a function. 7125c838251403b0be9a882540f1922577abba4c872ager@chromium.org Label shift_arguments; 71334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ Set(edx, Immediate(0)); // indicate regular JS_FUNCTION 7145c838251403b0be9a882540f1922577abba4c872ager@chromium.org { Label convert_to_object, use_global_receiver, patch_receiver; 7155c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Change context eagerly in case we need the global receiver. 7165c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 717b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 71849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Do not transform the receiver for strict mode functions. 71949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 72049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), 72149edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 72249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ j(not_equal, &shift_arguments); 72349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 7241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Do not transform the receiver for natives (shared already in ebx). 725d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset), 726d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org 1 << SharedFunctionInfo::kNativeBitWithinByte); 7276fe7a8e00388b38f66fc0127f3fe797d54b25492ricow@chromium.org __ j(not_equal, &shift_arguments); 7281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 72949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Compute the receiver in non-strict mode. 7305c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. 73140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org 73240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Call ToObject on the receiver if it is not an object, or use the 73340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // global object if it is null or undefined. 7347b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(ebx, &convert_to_object); 7357979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ cmp(ebx, factory->null_value()); 736b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ j(equal, &use_global_receiver); 7377979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ cmp(ebx, factory->undefined_value()); 738b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ j(equal, &use_global_receiver); 739d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 740d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); 74140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ j(above_equal, &shift_arguments); 742b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7435c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ bind(&convert_to_object); 744b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 745c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { // In order to preserve argument count. 746c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 747c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiTag(eax); 748c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 749c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 750c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 751c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 752c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, eax); 753c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Set(edx, Immediate(0)); // restore 754c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 755c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(eax); 756c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiUntag(eax); 757c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 758b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7595c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Restore the function to edi. 7605c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); 761b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ jmp(&patch_receiver); 762b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7635c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Use the global receiver object from the called function as the 7645c838251403b0be9a882540f1922577abba4c872ager@chromium.org // receiver. 765b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&use_global_receiver); 766b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org const int kGlobalIndex = 76746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; 768b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ mov(ebx, FieldOperand(esi, kGlobalIndex)); 76946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset)); 7703811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org __ mov(ebx, FieldOperand(ebx, kGlobalIndex)); 7715a8ca6c70c6fc9716f18f6223c98d1fef5752cf6kasperl@chromium.org __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 772b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 773b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&patch_receiver); 774b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ mov(Operand(esp, eax, times_4, 0), ebx); 775b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7765c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ jmp(&shift_arguments); 777846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org } 778846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org 77934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // 3b. Check for function proxy. 78034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ bind(&slow); 78134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ Set(edx, Immediate(1)); // indicate function proxy 78234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 78334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(equal, &shift_arguments); 78434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ bind(&non_function); 78534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ Set(edx, Immediate(2)); // indicate non-function 78634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 78734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // 3c. Patch the first argument when calling a non-function. The 7885c838251403b0be9a882540f1922577abba4c872ager@chromium.org // CALL_NON_FUNCTION builtin expects the non-function callee as 7895c838251403b0be9a882540f1922577abba4c872ager@chromium.org // receiver, so overwrite the first argument which will ultimately 7905c838251403b0be9a882540f1922577abba4c872ager@chromium.org // become the receiver. 7915c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(Operand(esp, eax, times_4, 0), edi); 7925c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7935c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 4. Shift arguments and return address one slot down on the stack 7945c838251403b0be9a882540f1922577abba4c872ager@chromium.org // (overwriting the original receiver). Adjust argument count to make 7955c838251403b0be9a882540f1922577abba4c872ager@chromium.org // the original first argument the new receiver. 7965c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ bind(&shift_arguments); 797b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org { Label loop; 798846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org __ mov(ecx, eax); 799b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&loop); 800b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ mov(ebx, Operand(esp, ecx, times_4, 0)); 801b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx); 802b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ dec(ecx); 8035c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ j(not_sign, &loop); // While non-negative (to copy return address). 804846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org __ pop(ebx); // Discard copy of return address. 805846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org __ dec(eax); // One fewer argument (first argument is new receiver). 806b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 807b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 80834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 80934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // or a function proxy via CALL_FUNCTION_PROXY. 81034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org { Label function, non_proxy; 811c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(edx, edx); 81234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(zero, &function); 8135d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org __ Set(ebx, Immediate(0)); 814c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(edx, Immediate(1)); 81534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(not_equal, &non_proxy); 81634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 81734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ pop(edx); // return address 81834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ push(edi); // re-add proxy object as additional argument 81934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ push(edx); 82034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ inc(eax); 821c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org __ SetCallKind(ecx, CALL_AS_FUNCTION); 82234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 82334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 82434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org RelocInfo::CODE_TARGET); 82534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 82634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ bind(&non_proxy); 827c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org __ SetCallKind(ecx, CALL_AS_METHOD); 82834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 8297979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 8307979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org RelocInfo::CODE_TARGET); 8315c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ bind(&function); 832b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 833b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 8345c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 5b. Get the code to call from the function and check that the number of 8355c838251403b0be9a882540f1922577abba4c872ager@chromium.org // expected arguments matches what we're providing. If so, jump 8365c838251403b0be9a882540f1922577abba4c872ager@chromium.org // (tail-call) to the code in register edx without checking arguments. 8375c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 8385c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(ebx, 8395c838251403b0be9a882540f1922577abba4c872ager@chromium.org FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 840145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 84130ce411529579186181838984710b0b0980857aaricow@chromium.org __ SmiUntag(ebx); 84240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ SetCallKind(ecx, CALL_AS_METHOD); 843c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ebx); 8447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ j(not_equal, 8457979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); 8465c838251403b0be9a882540f1922577abba4c872ager@chromium.org 847b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org ParameterCount expected(0); 848c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper(), 849c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com CALL_AS_METHOD); 850b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org} 851b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 852b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 85343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 85434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kArgumentsOffset = 2 * kPointerSize; 85534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kReceiverOffset = 3 * kPointerSize; 85634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kFunctionOffset = 4 * kPointerSize; 857c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 858c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope frame_scope(masm, StackFrame::INTERNAL); 859c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 860c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebp, kFunctionOffset)); // push this 861c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebp, kArgumentsOffset)); // push arguments 862c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 863c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 864c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check the stack for overflow. We are not trying to catch 865c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // interruptions (e.g. debug break and preemption) here, so the "real stack 866c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // limit" is checked. 867c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label okay; 868c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference real_stack_limit = 869c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::address_of_real_stack_limit(masm->isolate()); 870c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand::StaticVariable(real_stack_limit)); 871c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Make ecx the space we have left. The stack might already be overflowed 872c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // here which will cause ecx to become negative. 873c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, esp); 874c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(ecx, edi); 875c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Make edx the space we need for the array when it is unrolled onto the 876c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // stack. 877c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, eax); 878c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ shl(edx, kPointerSizeLog2 - kSmiTagSize); 879c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check if the arguments will overflow the stack. 880c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ecx, edx); 881c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(greater, &okay); // Signed comparison. 882c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 883c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Out of stack space. 884c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebp, 4 * kPointerSize)); // push this 885c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 886c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); 887c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&okay); 888c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // End of stack check. 889c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 890c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push current index and limit. 891c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int kLimitOffset = 892c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 893c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 894c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); // limit 895c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Immediate(0)); // index 896c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 897c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the receiver. 898c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(ebp, kReceiverOffset)); 899c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 900c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check that the function is a JS function (otherwise it must be a proxy). 901c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label push_receiver; 902c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand(ebp, kFunctionOffset)); 903c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 904c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &push_receiver); 905c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 906c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Change context eagerly to get the right global object if necessary. 907c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 90834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 909c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Compute the receiver. 910c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Do not transform the receiver for strict mode functions. 911c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label call_to_object, use_global_receiver; 912c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 913c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), 914c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 915c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &push_receiver); 91634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 917c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Factory* factory = masm->isolate()->factory(); 91843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 919c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Do not transform the receiver for natives (shared already in ecx). 920c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), 921c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1 << SharedFunctionInfo::kNativeBitWithinByte); 922c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &push_receiver); 92349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 924c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Compute the receiver in non-strict mode. 925c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Call ToObject on the receiver if it is not an object, or use the 926c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // global object if it is null or undefined. 927c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfSmi(ebx, &call_to_object); 928c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ebx, factory->null_value()); 929c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(equal, &use_global_receiver); 930c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ebx, factory->undefined_value()); 931c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(equal, &use_global_receiver); 932c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 933c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); 934c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(above_equal, &push_receiver); 9351c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 936c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&call_to_object); 937c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 938c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 939c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, eax); 940c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&push_receiver); 94143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 942c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Use the current global receiver object as the receiver. 943c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&use_global_receiver); 944c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int kGlobalOffset = 94546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; 946c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, FieldOperand(esi, kGlobalOffset)); 94746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset)); 948c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, FieldOperand(ebx, kGlobalOffset)); 949c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 95043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 951c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the receiver. 952c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&push_receiver); 953c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 95443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 955c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy all arguments from the array to the stack. 956c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label entry, loop; 9571044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(ecx, Operand(ebp, kIndexOffset)); 958c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 959c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 960c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, Operand(ebp, kArgumentsOffset)); // load arguments 96143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 962c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Use inline caching to speed up access to arguments. 963c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize(); 964c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ call(ic, RelocInfo::CODE_TARGET); 965c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // It is important that we do not have a test instruction after the 966c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // call. A test instruction after the call is used to indicate that 967c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // we have generated an inline version of the keyed load. In this 968c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // case, we know that we are not generating a test instruction next. 96943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 970c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the nth argument. 971c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 97243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 973c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Update the index on the stack and in register eax. 9741044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(ecx, Operand(ebp, kIndexOffset)); 9751044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ add(ecx, Immediate(1 << kSmiTagSize)); 9761044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(Operand(ebp, kIndexOffset), ecx); 97734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 978c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 9791044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ cmp(ecx, Operand(ebp, kLimitOffset)); 980c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &loop); 981c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 982c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Invoke the function. 983c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label call_proxy; 9841044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(eax, ecx); 985c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(eax); 986c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiUntag(eax); 987c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand(ebp, kFunctionOffset)); 988c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 989c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &call_proxy); 990c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(edi, actual, CALL_FUNCTION, 991c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com NullCallWrapper(), CALL_AS_METHOD); 992c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 993c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com frame_scope.GenerateLeaveFrame(); 994c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ ret(3 * kPointerSize); // remove this, receiver, and arguments 995c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 996c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Invoke the function proxy. 997c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&call_proxy); 998c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); // add function proxy as last argument 999c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ inc(eax); 1000c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Set(ebx, Immediate(0)); 1001c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SetCallKind(ecx, CALL_AS_METHOD); 1002c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 1003c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1004c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RelocInfo::CODE_TARGET); 100534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 1006c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Leave internal frame. 1007c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 100834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ ret(3 * kPointerSize); // remove this, receiver, and arguments 100943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 101043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 101143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 10123c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.orgvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 10133c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // ----------- S t a t e ------------- 10143c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // -- eax : argc 10153c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // -- esp[0] : return address 10163c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // -- esp[4] : last argument 10173c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // ----------------------------------- 10183c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org Label generic_array_code; 10193c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10203c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // Get the InternalArray function. 10213c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); 10223c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10233c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org if (FLAG_debug_code) { 1024fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Initial map for the builtin InternalArray function should be a map. 10253c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 10263c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // Will both indicate a NULL and a Smi. 10273c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ test(ebx, Immediate(kSmiTagMask)); 1028594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction); 10293c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ CmpObjectType(ebx, MAP_TYPE, ecx); 1030594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction); 10313c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org } 10323c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10333c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // Run the native code for the InternalArray function called as a normal 10343c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // function. 10351510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // tail call a stub 10361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org InternalArrayConstructorStub stub(masm->isolate()); 10371510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ TailCallStub(&stub); 10383c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org} 10393c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10403c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10412bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.comvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 10422bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // ----------- S t a t e ------------- 10432bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // -- eax : argc 10442bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // -- esp[0] : return address 10452bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // -- esp[4] : last argument 10462bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // ----------------------------------- 1047dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org Label generic_array_code; 10482bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 10492bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // Get the Array function. 1050d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); 10512bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 10522bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com if (FLAG_debug_code) { 1053fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Initial map for the builtin Array function should be a map. 10542bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 10552bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // Will both indicate a NULL and a Smi. 10562bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com __ test(ebx, Immediate(kSmiTagMask)); 1057594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); 10582bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com __ CmpObjectType(ebx, MAP_TYPE, ecx); 1059594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedInitialMapForArrayFunction); 10602bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com } 10612bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 10622bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // Run the native code for the Array function called as a normal function. 10631510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // tail call a stub 10641510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Handle<Object> undefined_sentinel( 10651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org masm->isolate()->heap()->undefined_value(), 10661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org masm->isolate()); 10671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ mov(ebx, Immediate(undefined_sentinel)); 10681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ArrayConstructorStub stub(masm->isolate()); 10691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ TailCallStub(&stub); 10702bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com} 10712bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 10722bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 1073d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.orgvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) { 1074d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------- S t a t e ------------- 1075d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- eax : number of arguments 1076d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- edi : constructor function 1077d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[0] : return address 1078d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1079d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[(argc + 1) * 4] : receiver 1080d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------------------------------- 10817979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Counters* counters = masm->isolate()->counters(); 10827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_calls(), 1); 1083d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1084d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org if (FLAG_debug_code) { 1085d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); 1086c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(edi, ecx); 1087594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedStringFunction); 1088d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org } 1089d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1090d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Load the first argument into eax and get rid of the rest 1091d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // (including the receiver). 1092d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label no_arguments; 1093c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(eax, eax); 1094d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ j(zero, &no_arguments); 1095d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); 1096d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ pop(ecx); 1097d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1098d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ push(ecx); 1099d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(eax, ebx); 1100d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1101d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Lookup the argument in the number to string cache. 1102d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label not_cached, argument_is_string; 1103528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ LookupNumberStringCache(eax, // Input. 1104528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ebx, // Result. 1105528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ecx, // Scratch 1. 1106528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org edx, // Scratch 2. 1107528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ¬_cached); 11087979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_cached_number(), 1); 1109d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&argument_is_string); 1110d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------- S t a t e ------------- 1111d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- ebx : argument converted to string 1112d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- edi : constructor function 1113d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[0] : return address 1114d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------------------------------- 1115d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1116d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Allocate a JSValue and put the tagged pointer into eax. 1117d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label gc_required; 11182bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org __ Allocate(JSValue::kSize, 11192bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org eax, // Result. 11202bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org ecx, // New allocation top (we ignore it). 11212bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org no_reg, 11222bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org &gc_required, 11232bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org TAG_OBJECT); 1124d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1125d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Set the map. 1126d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ LoadGlobalFunctionInitialMap(edi, ecx); 1127d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org if (FLAG_debug_code) { 1128d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), 1129d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org JSValue::kSize >> kPointerSizeLog2); 1130594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedStringWrapperInstanceSize); 1131d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); 1132594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper); 1133d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org } 1134d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); 1135d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1136d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Set properties and elements. 11377979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Factory* factory = masm->isolate()->factory(); 11387979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ Set(ecx, Immediate(factory->empty_fixed_array())); 1139d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); 1140d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); 1141d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1142d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Set the value. 1143d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); 1144d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1145d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Ensure the object is fully initialized. 1146d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); 1147d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1148d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // We're done. Return. 1149d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ ret(0); 1150d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1151d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // The argument was not found in the number to string cache. Check 1152d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // if it's a string already before calling the conversion builtin. 1153d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label convert_argument; 1154d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(¬_cached); 1155d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 11567b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(eax, &convert_argument); 1157d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); 1158d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ j(NegateCondition(is_string), &convert_argument); 1159d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(ebx, eax); 11607979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_string_value(), 1); 1161d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ jmp(&argument_is_string); 1162d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1163d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Invoke the conversion builtin and put the result into ebx. 1164d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&convert_argument); 11657979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_conversions(), 1); 1166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1167c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 1168c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); // Preserve the function. 1169c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 1170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 1171c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(edi); 1172c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1173d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(ebx, eax); 1174d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ jmp(&argument_is_string); 1175d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1176d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Load the empty string into ebx, remove the receiver from the 1177d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // stack, and jump back to the case where the argument is a string. 1178d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&no_arguments); 11797979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ Set(ebx, Immediate(factory->empty_string())); 1180d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ pop(ecx); 1181d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ lea(esp, Operand(esp, kPointerSize)); 1182d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ push(ecx); 1183d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ jmp(&argument_is_string); 1184d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1185d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // At this point the argument is already a string. Call runtime to 1186d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // create a string wrapper. 1187d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&gc_required); 11887979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_gc_required(), 1); 1189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1190c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 1191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 1192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kNewStringWrapper, 1); 1193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1194d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ ret(0); 1195d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org} 1196d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1197d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 119843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 119943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(ebp); 1200c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebp, esp); 120143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 120243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Store the arguments adaptor context sentinel. 120318ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 120443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 120543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Push the function on the stack. 120643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(edi); 120743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 120840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Preserve the number of arguments on the stack. Must preserve eax, 120940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // ebx and ecx because these registers are used when copying the 121043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // arguments and the receiver. 121180c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kSmiTagSize == 1); 121240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ lea(edi, Operand(eax, eax, times_1, kSmiTag)); 121340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ push(edi); 121443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 121543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 121643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 12177c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.orgstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 121843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Retrieve the number of arguments from the stack. 121943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 122043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 122143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Leave the frame. 122243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ leave(); 122343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 122443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Remove caller arguments from the stack. 122580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 122643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ pop(ecx); 122743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 122843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(ecx); 122943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 123043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 123143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 123243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 123343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ----------- S t a t e ------------- 123443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // -- eax : actual number of arguments 123543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // -- ebx : expected number of arguments 123640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // -- ecx : call kind information 123743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // -- edx : code entry to call 123843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ----------------------------------- 123943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1240b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org Label invoke, dont_adapt_arguments; 12417979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); 124243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 124343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label enough, too_few; 1244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ebx); 124543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ j(less, &too_few); 1246b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 1247b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ j(equal, &dont_adapt_arguments); 124843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 124943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen { // Enough parameters: Actual >= expected. 125043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&enough); 125143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen EnterArgumentsAdaptorFrame(masm); 125243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 125343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Copy receiver and all expected arguments. 125443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const int offset = StandardFrameConstants::kCallerSPOffset; 125543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(eax, Operand(ebp, eax, times_4, offset)); 125640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ mov(edi, -1); // account for receiver 125743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 125843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label copy; 125943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(©); 126040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ inc(edi); 126143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(Operand(eax, 0)); 1262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(eax, Immediate(kPointerSize)); 1263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(edi, ebx); 126443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ j(less, ©); 126543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ jmp(&invoke); 126643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 126743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 126843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen { // Too few parameters: Actual < expected. 126943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&too_few); 127043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen EnterArgumentsAdaptorFrame(masm); 127143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 127243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Copy receiver and all actual arguments. 127343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const int offset = StandardFrameConstants::kCallerSPOffset; 127443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(edi, Operand(ebp, eax, times_4, offset)); 127540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // ebx = expected - actual. 1276c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(ebx, eax); 127740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // eax = -actual - 1 127840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ neg(eax); 1279c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(eax, Immediate(1)); 128043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 128143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label copy; 128243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(©); 128340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ inc(eax); 128443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(Operand(edi, 0)); 1285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(edi, Immediate(kPointerSize)); 1286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(eax, eax); 128740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ j(not_zero, ©); 128843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 128943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Fill remaining expected arguments with undefined values. 129043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label fill; 129143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&fill); 129240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ inc(eax); 12937979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ push(Immediate(masm->isolate()->factory()->undefined_value())); 1294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ebx); 129543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ j(less, &fill); 129643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 129743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1298b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // Call the entry point. 129943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&invoke); 130040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Restore function pointer. 130140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ call(edx); 130343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1304967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org // Store offset of return address for deoptimizer. 1305659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 1306967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org 13077c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org // Leave frame and return. 13087c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org LeaveArgumentsAdaptorFrame(masm); 130943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ ret(0); 131043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 131143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ------------------------------------------- 1312b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // Dont adapt arguments. 131343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ------------------------------------------- 1314b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&dont_adapt_arguments); 1315c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(edx); 131643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 131743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 131843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1319a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1320e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org // Lookup the function in the JavaScript frame. 1321a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 1324e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org // Lookup and calculate pc offset. 1325e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerPCOffset)); 1326e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ mov(ebx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset)); 1327e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ sub(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 1328e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ sub(edx, FieldOperand(ebx, SharedFunctionInfo::kCodeOffset)); 1329e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ SmiTag(edx); 1330e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org 1331e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org // Pass both function and pc offset as arguments. 1332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 1333e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ push(edx); 1334e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2); 1335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1336a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 133783a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Label skip; 1338c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // If the code object is null, just return to the unoptimized code. 1339c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ cmp(eax, Immediate(0)); 134083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ j(not_equal, &skip, Label::kNear); 1341a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ret(0); 1342a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1343a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&skip); 1344c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1345c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Load deoptimization data from the code object. 1346c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag)); 1347c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1348c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Load the OSR entrypoint offset from the deoptimization data. 1349c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt( 1350c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag)); 1351c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ SmiUntag(ebx); 1352c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1353c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Compute the target address = code_obj + header_size + osr_offset 1354c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag)); 1355c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1356c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Overwrite the return address on the stack. 1357c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ mov(Operand(esp, 0), eax); 1358c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1359c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // And "return" to the OSR entry point of the function. 1360c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ ret(0); 1361a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 1362a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1363a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 13648e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.orgvoid Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) { 13658e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org // We check the stack limit as indicator that recompilation might be done. 13668e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org Label ok; 13678e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org ExternalReference stack_limit = 13688e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org ExternalReference::address_of_stack_limit(masm->isolate()); 13698e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ cmp(esp, Operand::StaticVariable(stack_limit)); 13708e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ j(above_equal, &ok, Label::kNear); 13718e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org { 13728e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 13738e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ CallRuntime(Runtime::kStackGuard, 0); 13748e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org } 13758e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ jmp(masm->isolate()->builtins()->OnStackReplacement(), 13768e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org RelocInfo::CODE_TARGET); 13778e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org 13788e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ bind(&ok); 13798e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ ret(0); 13808e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org} 13818e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org 138243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#undef __ 13837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org} 13847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org} // namespace v8::internal 13859dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com 13869dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif // V8_TARGET_ARCH_IA32 1387