1fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32 89dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com 9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h" 10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/deoptimizer.h" 11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/full-codegen.h" 12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/stub-cache.h" 1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 { 1571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal { 1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1865dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#define __ ACCESS_MASM(masm) 1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 21b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_Adaptor(MacroAssembler* masm, 22b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org CFunctionId id, 23b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org BuiltinExtraArguments extra_args) { 24b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // ----------- S t a t e ------------- 25b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- eax : number of arguments excluding receiver 26b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- edi : called function (only guaranteed when 27b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // extra_args requires it) 28b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esi : context 29b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[0] : return address 30b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[4] : last argument 31b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- ... 32b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[4 * argc] : first argument (argc == eax) 33b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // -- esp[4 * (argc +1)] : receiver 34b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // ----------------------------------- 35b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 36b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // Insert extra arguments. 37b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org int num_extra_args = 0; 38b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org if (extra_args == NEEDS_CALLED_FUNCTION) { 39b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org num_extra_args = 1; 40b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org Register scratch = ebx; 41b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org __ pop(scratch); // Save return address. 42b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org __ push(edi); 43b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org __ push(scratch); // Restore return address. 44b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } else { 45b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 46b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } 47b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 48ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org // JumpToExternalReference expects eax to contain the number of arguments 49b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org // including the receiver and the extra arguments. 50c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ add(eax, Immediate(num_extra_args + 1)); 51ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org __ JumpToExternalReference(ExternalReference(id, masm->isolate())); 5243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 5343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 5443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 554954674151afa960af66efb4831df06bde727333yangguo@chromium.orgstatic void CallRuntimePassFunction( 564954674151afa960af66efb4831df06bde727333yangguo@chromium.org MacroAssembler* masm, Runtime::FunctionId function_id) { 574a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 584a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Push a copy of the function. 594a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ push(edi); 604a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Function is also the parameter to the runtime call. 614a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ push(edi); 624a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 634a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ CallRuntime(function_id, 1); 644a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Restore receiver. 654a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ pop(edi); 664a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org} 674a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 684a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 69304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.orgstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) { 70304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 71304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset)); 72304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 73304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org __ jmp(eax); 74304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org} 75304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org 76304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org 774954674151afa960af66efb4831df06bde727333yangguo@chromium.orgstatic void GenerateTailCallToReturnedCode(MacroAssembler* masm) { 784954674151afa960af66efb4831df06bde727333yangguo@chromium.org __ lea(eax, FieldOperand(eax, Code::kHeaderSize)); 794954674151afa960af66efb4831df06bde727333yangguo@chromium.org __ jmp(eax); 804954674151afa960af66efb4831df06bde727333yangguo@chromium.org} 814954674151afa960af66efb4831df06bde727333yangguo@chromium.org 824954674151afa960af66efb4831df06bde727333yangguo@chromium.org 834954674151afa960af66efb4831df06bde727333yangguo@chromium.orgvoid Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) { 844a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Checking whether the queued function is ready for install is optional, 854a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // since we come across interrupts and stack checks elsewhere. However, 864a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // not checking may delay installing ready functions, and always checking 874a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // would be quite expensive. A good compromise is to first check against 884a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // stack limit as a cue for an interrupt signal. 894a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org Label ok; 904a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org ExternalReference stack_limit = 914a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org ExternalReference::address_of_stack_limit(masm->isolate()); 924a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ cmp(esp, Operand::StaticVariable(stack_limit)); 934a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ j(above_equal, &ok, Label::kNear); 944a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 95895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org CallRuntimePassFunction(masm, Runtime::kHiddenTryInstallOptimizedCode); 964954674151afa960af66efb4831df06bde727333yangguo@chromium.org GenerateTailCallToReturnedCode(masm); 974a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 984a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ bind(&ok); 994a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org GenerateTailCallToSharedCode(masm); 1006e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org} 1016e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org 1026e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org 103fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgstatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 104fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org bool is_api_function, 10569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org bool create_memento) { 106b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // ----------- S t a t e ------------- 107b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // -- eax: number of arguments 108b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // -- edi: constructor function 10969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // -- ebx: allocation site or undefined 110b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // ----------------------------------- 111b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 11269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Should never create mementos for api functions. 11369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org ASSERT(!is_api_function || !create_memento); 11469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 1157c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org // Enter a construct frame. 116c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 117c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::CONSTRUCT); 11843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 11969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 12069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ AssertUndefinedOrAllocationSite(ebx); 12169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ push(ebx); 12269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 12369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 124c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Store a smi-tagged arguments count on the stack. 125c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiTag(eax); 126c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 12743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 128c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the function to invoke on the stack. 129c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); 13043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Try to allocate the object without transitioning into C code. If any of 132c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // the preconditions is not met, the code bails out to the runtime call. 133c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label rt_call, allocated; 134c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (FLAG_inline_new) { 135c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label undo_allocation; 136c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference debug_step_in_fp = 137c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::debug_step_in_fp_address(masm->isolate()); 138c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); 139c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &rt_call); 14043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Verified that the constructor is a JSFunction. 142c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the initial map and verify that it is in fact a map. 143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 144c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Will both indicate a NULL and a Smi 146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfSmi(eax, &rt_call); 147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map (if proven valid below) 149c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(eax, MAP_TYPE, ebx); 150c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &rt_call); 151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 152c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check that the constructor is not constructing a JSFunction (see 153c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // comments in Runtime_NewObject in runtime.cc). In which case the 154c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // initial map's instance type would be JS_FUNCTION_TYPE. 155c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 156c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpInstanceType(eax, JS_FUNCTION_TYPE); 158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(equal, &rt_call); 1594a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 160011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (!is_api_function) { 161c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label allocate; 162011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // The code below relies on these assumptions. 163011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org STATIC_ASSERT(JSFunction::kNoSlackTracking == 0); 164011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org STATIC_ASSERT(Map::ConstructionCount::kShift + 165011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Map::ConstructionCount::kSize == 32); 166011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Check if slack tracking is enabled. 167011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ mov(esi, FieldOperand(eax, Map::kBitField3Offset)); 168011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ shr(esi, Map::ConstructionCount::kShift); 169011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ j(zero, &allocate); // JSFunction::kNoSlackTracking 170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Decrease generous allocation count. 171011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ sub(FieldOperand(eax, Map::kBitField3Offset), 172011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Immediate(1 << Map::ConstructionCount::kShift)); 173011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 174011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ cmp(esi, JSFunction::kFinishSlackTracking); 175011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ j(not_equal, &allocate); 1764a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 177c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 178c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); 1794a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 180c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); // constructor 181895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1); 1824a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 183c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(edi); 184c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(eax); 185011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ xor_(esi, esi); // JSFunction::kNoSlackTracking 1864a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&allocate); 188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 190c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Now allocate the JSObject on the heap. 191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: constructor 192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); 194c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ shl(edi, kPointerSizeLog2); 19569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 19669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ add(edi, Immediate(AllocationMemento::kSize)); 19769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 19869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 199f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); 20069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 20169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org Factory* factory = masm->isolate()->factory(); 20269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocated the JSObject, now initialize the fields. 204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 20669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // edi: start of next object (including memento if create_memento) 207c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(ebx, JSObject::kMapOffset), eax); 208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, factory->empty_fixed_array()); 209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); 210c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); 211c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Set extra fields in the newly allocated object. 212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 21469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // edi: start of next object (including memento if create_memento) 215011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // esi: slack tracking counter (non-API function case) 216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, factory->undefined_value()); 217011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); 218011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (!is_api_function) { 219011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Label no_inobject_slack_tracking; 220011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 221011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Check if slack tracking is enabled. 222011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ cmp(esi, JSFunction::kNoSlackTracking); 223011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ j(equal, &no_inobject_slack_tracking); 224011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 225011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Allocate object with a slack. 226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(esi, 227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lea(esi, 229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize)); 230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // esi: offset of first field after pre-allocated fields 231c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (FLAG_debug_code) { 232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(esi, edi); 233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Assert(less_equal, 234594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org kUnexpectedNumberOfPreAllocatedPropertyFields); 235c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InitializeFieldsWithFiller(ecx, esi, edx); 2377979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ mov(edx, factory->one_pointer_filler_map()); 238011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Fill the remaining fields with one pointer filler map. 239011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 240011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ bind(&no_inobject_slack_tracking); 241011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org } 242011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 243011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (create_memento) { 24469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ lea(esi, Operand(edi, -AllocationMemento::kSize)); 24569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ InitializeFieldsWithFiller(ecx, esi, edx); 24669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 24769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Fill in memento fields if necessary. 24869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // esi: points to the allocated but uninitialized memento. 24969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ mov(Operand(esi, AllocationMemento::kMapOffset), 250011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org factory->allocation_memento_map()); 25169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Get the cell or undefined. 25269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ mov(edx, Operand(esp, kPointerSize*2)); 25369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset), 25469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org edx); 25569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } else { 25669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ InitializeFieldsWithFiller(ecx, edi, edx); 257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 259c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Add the object tag to make the JSObject real, so that we can continue 260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // and jump into the continuation code at any time from now on. Any 261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // failures need to undo the allocation, so that the heap is in a 262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // consistent state and verifiable. 263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 265c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object 266c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ or_(ebx, Immediate(kHeapObjectTag)); 267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check if a non-empty properties array is needed. 269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocate and initialize a FixedArray if it is. 270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // eax: initial map 271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object 273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Calculate the total number of properties described by the map. 274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset)); 275c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(ecx, 276c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset)); 277c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ add(edx, ecx); 278c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Calculate unused properties past the end of the in-object properties. 279c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset)); 280c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(edx, ecx); 281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Done if no extra properties are to be allocated. 282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(zero, &allocated); 283594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(positive, kPropertyAllocationCountFailed); 284c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Scale the number of elements by pointer size and add the header for 286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // FixedArrays to the start of the next object calculation from above. 287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: start of next object (will be start of FixedArray) 289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edx: number of elements in properties array 290f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate(FixedArray::kHeaderSize, 291f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org times_pointer_size, 292f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org edx, 293f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org REGISTER_VALUE_IS_INT32, 294f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org edi, 295f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org ecx, 296f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org no_reg, 297f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org &undo_allocation, 298f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org RESULT_CONTAINS_TOP); 299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initialize the FixedArray. 301c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: FixedArray 303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edx: number of elements 304c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ecx: start of next object 305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, factory->fixed_array_map()); 306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map 307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiTag(edx); 308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length 309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initialize the fields to undefined. 311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: FixedArray 313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ecx: start of next object 314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { Label loop, entry; 3157979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ mov(edx, factory->undefined_value()); 316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lea(eax, Operand(edi, FixedArray::kHeaderSize)); 317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(Operand(eax, 0), edx); 320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ add(eax, Immediate(kPointerSize)); 321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ecx); 323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(below, &loop); 3244a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org } 32543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Store the initialized FixedArray into the properties field of 327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // the JSObject 328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: FixedArray 330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag 331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi); 33243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 33343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Continue with JSObject being successfully allocated 335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject 336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&allocated); 33743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Undo the setting of the new top so that the heap is verifiable. For 339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // example, the map's unused properties potentially do not match the 340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // allocated objects unused properties. 341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: JSObject (previous new top) 342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&undo_allocation); 343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ UndoAllocationInNewSpace(ebx); 344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 34543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocate the new receiver object using the runtime call. 347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&rt_call); 34869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org int offset = 0; 34969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 35069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // Get the cell or allocation site. 35169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ mov(edi, Operand(esp, kPointerSize * 2)); 35269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ push(edi); 35369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org offset = kPointerSize; 35469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 35569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 356011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org // Must restore esi (context) and edi (constructor) before calling runtime. 357011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 35869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ mov(edi, Operand(esp, offset)); 359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // edi: function (constructor) 360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); 36169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 362895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNewObjectWithAllocationSite, 2); 36369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } else { 364895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNewObject, 1); 36569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, eax); // store result in ebx 36743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 36869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // If we ended up using the runtime, and we want a memento, then the 36969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // runtime call made it for us, and we shouldn't do create count 37069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // increment. 37169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org Label count_incremented; 37269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 37369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ jmp(&count_incremented); 37469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 37569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // New object allocated. 377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // ebx: newly allocated object 378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&allocated); 37969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 38069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org if (create_memento) { 38169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ mov(ecx, Operand(esp, kPointerSize * 2)); 38269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ cmp(ecx, masm->isolate()->factory()->undefined_value()); 38369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ j(equal, &count_incremented); 38469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // ecx is an AllocationSite. We are creating a memento from it, so we 38569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org // need to increment the memento create count. 38669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset), 38769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org Immediate(Smi::FromInt(1))); 38869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org __ bind(&count_incremented); 38969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org } 39069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org 391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Retrieve the function from the stack. 392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(edi); 39343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Retrieve smi-tagged arguments count from the stack. 395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, Operand(esp, 0)); 396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiUntag(eax); 39743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the allocated receiver to the stack. We need two copies 399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // because we may have to return the original one and the calling 400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // conventions dictate that the called function pops the receiver. 401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 40343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 404f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up pointer to last argument. 405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); 40643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 407c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy arguments and receiver to the expression stack. 408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label loop, entry; 409c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, eax); 410c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 412c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebx, ecx, times_4, 0)); 413c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 414c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ dec(ecx); 415c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(greater_equal, &loop); 416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Call the function. 418c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (is_api_function) { 419c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 420c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Handle<Code> code = 421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com masm->isolate()->builtins()->HandleApiCallConstruct(); 42226ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org __ call(code, RelocInfo::CODE_TARGET); 423c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(eax); 425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(edi, actual, CALL_FUNCTION, 426e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org NullCallWrapper()); 427c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 42843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 429967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org // Store offset of return address for deoptimizer. 430011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org if (!is_api_function) { 431967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 432967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org } 433967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org 434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Restore context from the frame. 435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 43643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the result is an object (in the ECMA sense), we should get rid 438c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // of the receiver and use the result; see ECMA-262 section 13.2.2-7 439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // on page 74. 440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label use_receiver, exit; 44143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the result is a smi, it is *not* an object in the ECMA sense. 443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfSmi(eax, &use_receiver); 44443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 445c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the type of the result (stored in its map) is less than 446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); 448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(above_equal, &exit); 44943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Throw away the result of the constructor invocation and use the 451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // on-stack receiver as the result. 452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&use_receiver); 453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, Operand(esp, 0)); 45443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Restore the arguments count and leave the construct frame. 456c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&exit); 457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(esp, kPointerSize)); // Get arguments count. 45843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 459c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Leave construct frame. 460c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 46143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 46243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Remove caller arguments from the stack and return. 46380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 46443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ pop(ecx); 46543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 46643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(ecx); 4677979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1); 46843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ ret(0); 46943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 47043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 47143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 472b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 473011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); 474b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org} 475b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 476b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 477b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.orgvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 478011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org Generate_JSConstructStubHelper(masm, true, false); 479b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org} 480b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 481b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 48243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 48343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen bool is_construct) { 4841510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ProfileEntryHookStub::MaybeCallEntryHook(masm); 4851510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org 486c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Clear the context before we push it when entering the internal frame. 487a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(esi, Immediate(0)); 48843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 49143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the previous frame pointer (ebx) to access C arguments 493c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(ebp, 0)); 49443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 495c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the function from the frame and setup the context. 496c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); 497c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); 49843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the function and the receiver onto the stack. 500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ecx); 501c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); 50243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the number of arguments and setup pointer to the arguments. 504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); 505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); 50643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy arguments to the stack in a loop. 508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label loop, entry; 509a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(ecx, Immediate(0)); 510c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 511c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv 513c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(edx, 0)); // dereference handle 514c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ inc(ecx); 515c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ecx, eax); 517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &loop); 518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the function from the stack and call it. 520c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // kPointerSize for the receiver. 521c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand(esp, eax, times_4, kPointerSize)); 522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Invoke the code. 524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (is_construct) { 525a53e8e03bcb23716d1025de362626f90f00da892svenpanne@chromium.org // No type feedback cell is available 5265697144afb43181fed170b81c194fe1cc0fce3b6machenbach@chromium.org __ mov(ebx, masm->isolate()->factory()->undefined_value()); 527a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); 528fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ CallStub(&stub); 529c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 530c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(eax); 531c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(edi, actual, CALL_FUNCTION, 532e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org NullCallWrapper()); 533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 53443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 535c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Exit the internal frame. Notice that this also removes the empty. 536c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // context and the function left on the stack by the code 537c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // invocation. 53843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ ret(kPointerSize); // Remove receiver. 54043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 54143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 54243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 54343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 54443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Generate_JSEntryTrampolineHelper(masm, false); 54543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 54643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 54743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 54843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 54943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Generate_JSEntryTrampolineHelper(masm, true); 55043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 55143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 55243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 5534954674151afa960af66efb4831df06bde727333yangguo@chromium.orgvoid Builtins::Generate_CompileUnoptimized(MacroAssembler* masm) { 554895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org CallRuntimePassFunction(masm, Runtime::kHiddenCompileUnoptimized); 5554954674151afa960af66efb4831df06bde727333yangguo@chromium.org GenerateTailCallToReturnedCode(masm); 556ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org} 557ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org 558ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org 5594954674151afa960af66efb4831df06bde727333yangguo@chromium.org 5604954674151afa960af66efb4831df06bde727333yangguo@chromium.orgstatic void CallCompileOptimized(MacroAssembler* masm, bool concurrent) { 5614954674151afa960af66efb4831df06bde727333yangguo@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 5624954674151afa960af66efb4831df06bde727333yangguo@chromium.org // Push a copy of the function. 5634954674151afa960af66efb4831df06bde727333yangguo@chromium.org __ push(edi); 5644954674151afa960af66efb4831df06bde727333yangguo@chromium.org // Function is also the parameter to the runtime call. 5654954674151afa960af66efb4831df06bde727333yangguo@chromium.org __ push(edi); 5664954674151afa960af66efb4831df06bde727333yangguo@chromium.org // Whether to compile in a background thread. 5674954674151afa960af66efb4831df06bde727333yangguo@chromium.org __ Push(masm->isolate()->factory()->ToBoolean(concurrent)); 5684954674151afa960af66efb4831df06bde727333yangguo@chromium.org 569895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenCompileOptimized, 2); 5704954674151afa960af66efb4831df06bde727333yangguo@chromium.org // Restore receiver. 5714954674151afa960af66efb4831df06bde727333yangguo@chromium.org __ pop(edi); 5724954674151afa960af66efb4831df06bde727333yangguo@chromium.org} 5734954674151afa960af66efb4831df06bde727333yangguo@chromium.org 5744954674151afa960af66efb4831df06bde727333yangguo@chromium.org 5754954674151afa960af66efb4831df06bde727333yangguo@chromium.orgvoid Builtins::Generate_CompileOptimized(MacroAssembler* masm) { 5764954674151afa960af66efb4831df06bde727333yangguo@chromium.org CallCompileOptimized(masm, false); 5774954674151afa960af66efb4831df06bde727333yangguo@chromium.org GenerateTailCallToReturnedCode(masm); 5784954674151afa960af66efb4831df06bde727333yangguo@chromium.org} 5794954674151afa960af66efb4831df06bde727333yangguo@chromium.org 5804954674151afa960af66efb4831df06bde727333yangguo@chromium.org 5814954674151afa960af66efb4831df06bde727333yangguo@chromium.orgvoid Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) { 5824954674151afa960af66efb4831df06bde727333yangguo@chromium.org CallCompileOptimized(masm, true); 5834954674151afa960af66efb4831df06bde727333yangguo@chromium.org GenerateTailCallToReturnedCode(masm); 584a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 585a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 586a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 587e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { 588e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // For now, we are relying on the fact that make_code_young doesn't do any 589e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // garbage collection which allows us to save/restore the registers without 590e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // worrying about which of them contain pointers. We also don't build an 591e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // internal frame to make the code faster, since we shouldn't have to do stack 592e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // crawls in MakeCodeYoung. This seems a bit fragile. 593e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 594e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // Re-execute the code that was patched back to the young age when 595e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org // the stub returns. 596e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ sub(Operand(esp, 0), Immediate(5)); 597e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ pushad(); 598e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ mov(eax, Operand(esp, 8 * kPointerSize)); 599e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org { 600e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 601528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ PrepareCallCFunction(2, ebx); 602528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ mov(Operand(esp, 1 * kPointerSize), 603528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org Immediate(ExternalReference::isolate_address(masm->isolate()))); 604e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ mov(Operand(esp, 0), eax); 605e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ CallCFunction( 606528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ExternalReference::get_make_code_young_function(masm->isolate()), 2); 607e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org } 608e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ popad(); 609e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org __ ret(0); 610e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org} 611e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 612e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \ 613e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainEvenMarking( \ 614e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org MacroAssembler* masm) { \ 615e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 616e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org} \ 617e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainOddMarking( \ 618e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org MacroAssembler* masm) { \ 619e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 620e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org} 621e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.orgCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR) 622e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR 623e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 624e4ac3ef2f6fa9300bc78c5a4cb7d4cb66ac6e83dmvstanton@chromium.org 625c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { 626c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact 627c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // that make_code_young doesn't do any garbage collection which allows us to 628c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // save/restore the registers without worrying about which of them contain 629c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // pointers. 630c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ pushad(); 631c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(eax, Operand(esp, 8 * kPointerSize)); 632c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ sub(eax, Immediate(Assembler::kCallInstructionLength)); 633c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org { // NOLINT 634c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 635c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ PrepareCallCFunction(2, ebx); 636c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(Operand(esp, 1 * kPointerSize), 637c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org Immediate(ExternalReference::isolate_address(masm->isolate()))); 638c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(Operand(esp, 0), eax); 639c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ CallCFunction( 640c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org ExternalReference::get_mark_code_as_executed_function(masm->isolate()), 641c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 2); 642c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org } 643c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ popad(); 644c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 645c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // Perform prologue operations usually performed by the young code stub. 646c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ pop(eax); // Pop return address into scratch register. 647c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(ebp); // Caller's frame pointer. 648c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ mov(ebp, esp); 649c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(esi); // Callee's context. 650c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(edi); // Callee's JS Function. 651c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ push(eax); // Push return address after frame prologue. 652c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 653c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // Jump to point after the code-age stub. 654c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ ret(0); 655c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org} 656c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 657c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 658c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) { 659c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org GenerateMakeCodeYoungAgainCommon(masm); 660c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org} 661c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 662c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 663f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm, 664f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SaveFPRegsMode save_doubles) { 665a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Enter an internal frame. 666a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org { 667a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 668a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 669a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Preserve registers across notification, this is important for compiled 670a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // stubs that tail call the runtime on deopts passing their parameters in 671a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // registers. 672a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ pushad(); 673895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNotifyStubFailure, 0, save_doubles); 674a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ popad(); 675a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org // Tear down internal frame. 676a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org } 677a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 678a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ pop(MemOperand(esp, 0)); // Ignore state offset 679a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org __ ret(0); // Return to IC Miss stub, continuation still on stack. 680a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org} 681a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 682a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org 683f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { 684f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs); 685f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 686f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 687f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 688f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) { 6893c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 690f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 691f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 692f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 693a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 694a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Deoptimizer::BailoutType type) { 695c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 696c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 697a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 698659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org // Pass deoptimization type to the runtime system. 699c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Immediate(Smi::FromInt(static_cast<int>(type)))); 700895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenNotifyDeoptimized, 1); 701a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 702c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Tear down internal frame. 703c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 704a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 705a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Get the full codegen state from the stack and untag it. 706a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(ecx, Operand(esp, 1 * kPointerSize)); 707a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ SmiUntag(ecx); 708a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 709a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org // Switch on the state. 71083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Label not_no_registers, not_tos_eax; 711a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ cmp(ecx, FullCodeGenerator::NO_REGISTERS); 71283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ j(not_equal, ¬_no_registers, Label::kNear); 713a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ret(1 * kPointerSize); // Remove state. 714a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 715a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(¬_no_registers); 716a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(eax, Operand(esp, 2 * kPointerSize)); 717a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ cmp(ecx, FullCodeGenerator::TOS_REG); 71883a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ j(not_equal, ¬_tos_eax, Label::kNear); 719a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ret(2 * kPointerSize); // Remove state, eax. 720a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 721a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(¬_tos_eax); 722594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Abort(kNoCasesLeft); 723a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 724a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 725a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 726a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 727a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 728a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 729a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 730a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 731aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.orgvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 732aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 733aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org} 734aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org 735aefd6076246d134fe4e1bf0641f0a4d4e35a09c2danno@chromium.org 736a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 737a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 738a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 739a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 740a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 741b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.orgvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 7427979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Factory* factory = masm->isolate()->factory(); 7437979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org 744b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // 1. Make sure we have at least one argument. 745b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org { Label done; 746c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(eax, eax); 7477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ j(not_zero, &done); 748b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ pop(ebx); 7497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ push(Immediate(factory->undefined_value())); 750b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ push(ebx); 751b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ inc(eax); 752b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&done); 753b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 754b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7555c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 2. Get the function to call (passed as receiver) from the stack, check 7565c838251403b0be9a882540f1922577abba4c872ager@chromium.org // if it is a function. 75734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org Label slow, non_function; 7585c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 1 ~ return address. 7595c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); 7607b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(edi, &non_function); 7615c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 76234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(not_equal, &slow); 763b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 764b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7655c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 3a. Patch the first argument if necessary when calling a function. 7665c838251403b0be9a882540f1922577abba4c872ager@chromium.org Label shift_arguments; 767a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(edx, Immediate(0)); // indicate regular JS_FUNCTION 7685c838251403b0be9a882540f1922577abba4c872ager@chromium.org { Label convert_to_object, use_global_receiver, patch_receiver; 7695c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Change context eagerly in case we need the global receiver. 7705c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 771b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 77249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org // Do not transform the receiver for strict mode functions. 77349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 77449edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), 77549edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 77649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org __ j(not_equal, &shift_arguments); 77749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 7781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org // Do not transform the receiver for natives (shared already in ebx). 779d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset), 780d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org 1 << SharedFunctionInfo::kNativeBitWithinByte); 7816fe7a8e00388b38f66fc0127f3fe797d54b25492ricow@chromium.org __ j(not_equal, &shift_arguments); 7821c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 783486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org // Compute the receiver in sloppy mode. 7845c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. 78540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org 78640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Call ToObject on the receiver if it is not an object, or use the 78740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // global object if it is null or undefined. 7887b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(ebx, &convert_to_object); 7897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ cmp(ebx, factory->null_value()); 790b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ j(equal, &use_global_receiver); 7917979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ cmp(ebx, factory->undefined_value()); 792b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ j(equal, &use_global_receiver); 793d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 794d2be901879306d8ff27e78e37783028d581d46fcricow@chromium.org __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); 79540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ j(above_equal, &shift_arguments); 796b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 7975c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ bind(&convert_to_object); 798b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 799c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { // In order to preserve argument count. 800c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 801c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiTag(eax); 802c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 803c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 804c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 805c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 806c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, eax); 807a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(edx, Immediate(0)); // restore 808c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 809c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(eax); 810c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiUntag(eax); 811c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 812b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 8135c838251403b0be9a882540f1922577abba4c872ager@chromium.org // Restore the function to edi. 8145c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); 815b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ jmp(&patch_receiver); 816b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 817b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&use_global_receiver); 818e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org __ mov(ebx, 819e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 820e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 821b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 822b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&patch_receiver); 823b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ mov(Operand(esp, eax, times_4, 0), ebx); 824b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 8255c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ jmp(&shift_arguments); 826846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org } 827846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org 82834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // 3b. Check for function proxy. 82934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ bind(&slow); 830a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(edx, Immediate(1)); // indicate function proxy 83134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); 83234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(equal, &shift_arguments); 83334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ bind(&non_function); 834a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(edx, Immediate(2)); // indicate non-function 83534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 83634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // 3c. Patch the first argument when calling a non-function. The 8375c838251403b0be9a882540f1922577abba4c872ager@chromium.org // CALL_NON_FUNCTION builtin expects the non-function callee as 8385c838251403b0be9a882540f1922577abba4c872ager@chromium.org // receiver, so overwrite the first argument which will ultimately 8395c838251403b0be9a882540f1922577abba4c872ager@chromium.org // become the receiver. 8405c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(Operand(esp, eax, times_4, 0), edi); 8415c838251403b0be9a882540f1922577abba4c872ager@chromium.org 8425c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 4. Shift arguments and return address one slot down on the stack 8435c838251403b0be9a882540f1922577abba4c872ager@chromium.org // (overwriting the original receiver). Adjust argument count to make 8445c838251403b0be9a882540f1922577abba4c872ager@chromium.org // the original first argument the new receiver. 8455c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ bind(&shift_arguments); 846b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org { Label loop; 847846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org __ mov(ecx, eax); 848b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&loop); 849b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ mov(ebx, Operand(esp, ecx, times_4, 0)); 850b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx); 851b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ dec(ecx); 8525c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ j(not_sign, &loop); // While non-negative (to copy return address). 853846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org __ pop(ebx); // Discard copy of return address. 854846fb74ad58083497b91fc4668a56fddb36fbd2esgjesse@chromium.org __ dec(eax); // One fewer argument (first argument is new receiver). 855b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 856b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 85734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 85834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org // or a function proxy via CALL_FUNCTION_PROXY. 85934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org { Label function, non_proxy; 860c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(edx, edx); 86134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(zero, &function); 862a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(ebx, Immediate(0)); 863c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(edx, Immediate(1)); 86434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ j(not_equal, &non_proxy); 86534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 86634e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ pop(edx); // return address 86734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ push(edi); // re-add proxy object as additional argument 86834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ push(edx); 86934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ inc(eax); 87034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 87134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 87234e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org RelocInfo::CODE_TARGET); 87334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 87434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ bind(&non_proxy); 87534e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 8767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 8777979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org RelocInfo::CODE_TARGET); 8785c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ bind(&function); 879b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org } 880b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 8815c838251403b0be9a882540f1922577abba4c872ager@chromium.org // 5b. Get the code to call from the function and check that the number of 8825c838251403b0be9a882540f1922577abba4c872ager@chromium.org // expected arguments matches what we're providing. If so, jump 8835c838251403b0be9a882540f1922577abba4c872ager@chromium.org // (tail-call) to the code in register edx without checking arguments. 8845c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 8855c838251403b0be9a882540f1922577abba4c872ager@chromium.org __ mov(ebx, 8865c838251403b0be9a882540f1922577abba4c872ager@chromium.org FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); 887145eff58d4f6ac0dcc53abb556dbf3cac6c3280aerik.corry@gmail.com __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 88830ce411529579186181838984710b0b0980857aaricow@chromium.org __ SmiUntag(ebx); 889c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ebx); 8907979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ j(not_equal, 8917979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org masm->isolate()->builtins()->ArgumentsAdaptorTrampoline()); 8925c838251403b0be9a882540f1922577abba4c872ager@chromium.org 893b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org ParameterCount expected(0); 894e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org __ InvokeCode(edx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); 895b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org} 896b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 897b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org 89843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 89934e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kArgumentsOffset = 2 * kPointerSize; 90034e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kReceiverOffset = 3 * kPointerSize; 90134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org static const int kFunctionOffset = 4 * kPointerSize; 902c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 903c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope frame_scope(masm, StackFrame::INTERNAL); 904c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 905c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebp, kFunctionOffset)); // push this 906c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebp, kArgumentsOffset)); // push arguments 907c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 908c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 909c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check the stack for overflow. We are not trying to catch 910c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // interruptions (e.g. debug break and preemption) here, so the "real stack 911c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // limit" is checked. 912c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label okay; 913c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference real_stack_limit = 914c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::address_of_real_stack_limit(masm->isolate()); 915c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand::StaticVariable(real_stack_limit)); 916c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Make ecx the space we have left. The stack might already be overflowed 917c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // here which will cause ecx to become negative. 918c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, esp); 919c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(ecx, edi); 920c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Make edx the space we need for the array when it is unrolled onto the 921c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // stack. 922c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, eax); 923c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ shl(edx, kPointerSizeLog2 - kSmiTagSize); 924c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check if the arguments will overflow the stack. 925c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ecx, edx); 926c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(greater, &okay); // Signed comparison. 927c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 928c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Out of stack space. 929c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Operand(ebp, 4 * kPointerSize)); // push this 930c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 931e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 932c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&okay); 933c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // End of stack check. 934c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 935c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push current index and limit. 936c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int kLimitOffset = 937c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 938c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 939c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); // limit 940c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(Immediate(0)); // index 941c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 942c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the receiver. 943c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, Operand(ebp, kReceiverOffset)); 944c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 945c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check that the function is a JS function (otherwise it must be a proxy). 946e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org Label push_receiver, use_global_receiver; 947c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand(ebp, kFunctionOffset)); 948c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 949c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &push_receiver); 950c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 951c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Change context eagerly to get the right global object if necessary. 952c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 95334e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 954c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Compute the receiver. 955c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Do not transform the receiver for strict mode functions. 956e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org Label call_to_object; 957c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 958c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), 959c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 960c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &push_receiver); 96134e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 962c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Factory* factory = masm->isolate()->factory(); 96343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 964c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Do not transform the receiver for natives (shared already in ecx). 965c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), 966c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1 << SharedFunctionInfo::kNativeBitWithinByte); 967c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &push_receiver); 96849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org 969486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org // Compute the receiver in sloppy mode. 970c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Call ToObject on the receiver if it is not an object, or use the 971c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // global object if it is null or undefined. 972c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ JumpIfSmi(ebx, &call_to_object); 973c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ebx, factory->null_value()); 974c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(equal, &use_global_receiver); 975c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(ebx, factory->undefined_value()); 976c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(equal, &use_global_receiver); 977c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 978c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); 979c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(above_equal, &push_receiver); 9801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 981c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&call_to_object); 982c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 983c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 984c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebx, eax); 985c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&push_receiver); 98643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 987c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&use_global_receiver); 988e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org __ mov(ebx, 989e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 990e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); 99143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 992c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the receiver. 993c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&push_receiver); 994c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 99543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 996c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy all arguments from the array to the stack. 997c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label entry, loop; 9981044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(ecx, Operand(ebp, kIndexOffset)); 999c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 1000c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 1001c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edx, Operand(ebp, kArgumentsOffset)); // load arguments 100243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1003c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Use inline caching to speed up access to arguments. 1004c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize(); 1005c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ call(ic, RelocInfo::CODE_TARGET); 1006c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // It is important that we do not have a test instruction after the 1007c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // call. A test instruction after the call is used to indicate that 1008c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // we have generated an inline version of the keyed load. In this 1009c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // case, we know that we are not generating a test instruction next. 101043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1011c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the nth argument. 1012c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 101343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1014c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Update the index on the stack and in register eax. 10151044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(ecx, Operand(ebp, kIndexOffset)); 10161044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ add(ecx, Immediate(1 << kSmiTagSize)); 10171044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(Operand(ebp, kIndexOffset), ecx); 101834e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 1019c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 10201044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ cmp(ecx, Operand(ebp, kLimitOffset)); 1021c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &loop); 1022c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1023e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org // Call the function. 1024c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label call_proxy; 10251044a4d5f9e933d03cf05a0d7d49d8afccec0879danno@chromium.org __ mov(eax, ecx); 1026c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(eax); 1027c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SmiUntag(eax); 1028c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(edi, Operand(ebp, kFunctionOffset)); 1029c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 1030c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ j(not_equal, &call_proxy); 1031e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper()); 1032c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1033c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com frame_scope.GenerateLeaveFrame(); 1034c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ ret(3 * kPointerSize); // remove this, receiver, and arguments 1035c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1036e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org // Call the function proxy. 1037c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&call_proxy); 1038c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); // add function proxy as last argument 1039c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ inc(eax); 1040a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(ebx, Immediate(0)); 1041c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY); 1042c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1043c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RelocInfo::CODE_TARGET); 104434e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org 1045c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Leave internal frame. 1046c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 104734e60787ea1e76f3ee49e859f71f036170c21f0elrn@chromium.org __ ret(3 * kPointerSize); // remove this, receiver, and arguments 104843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 104943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 105043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 10513c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.orgvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 10523c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // ----------- S t a t e ------------- 10533c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // -- eax : argc 10543c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // -- esp[0] : return address 10553c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // -- esp[4] : last argument 10563c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // ----------------------------------- 10573c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org Label generic_array_code; 10583c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10593c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // Get the InternalArray function. 10603c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, edi); 10613c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10623c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org if (FLAG_debug_code) { 1063fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Initial map for the builtin InternalArray function should be a map. 10643c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 10653c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // Will both indicate a NULL and a Smi. 10663c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ test(ebx, Immediate(kSmiTagMask)); 1067594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(not_zero, kUnexpectedInitialMapForInternalArrayFunction); 10683c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org __ CmpObjectType(ebx, MAP_TYPE, ecx); 1069594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedInitialMapForInternalArrayFunction); 10703c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org } 10713c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10723c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // Run the native code for the InternalArray function called as a normal 10733c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org // function. 10741510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // tail call a stub 10751510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org InternalArrayConstructorStub stub(masm->isolate()); 10761510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ TailCallStub(&stub); 10773c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org} 10783c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10793c93e774a3c6dc64c4d10d9cc7d5e071f0e8a28esvenpanne@chromium.org 10802bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.comvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 10812bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // ----------- S t a t e ------------- 10822bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // -- eax : argc 10832bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // -- esp[0] : return address 10842bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // -- esp[4] : last argument 10852bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // ----------------------------------- 1086dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org Label generic_array_code; 10872bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 10882bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // Get the Array function. 1089d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, edi); 10902bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 10912bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com if (FLAG_debug_code) { 1092fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org // Initial map for the builtin Array function should be a map. 10932bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 10942bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // Will both indicate a NULL and a Smi. 10952bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com __ test(ebx, Immediate(kSmiTagMask)); 1096594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); 10972bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com __ CmpObjectType(ebx, MAP_TYPE, ecx); 1098594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedInitialMapForArrayFunction); 10992bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com } 11002bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 11012bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com // Run the native code for the Array function called as a normal function. 11021510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // tail call a stub 11035697144afb43181fed170b81c194fe1cc0fce3b6machenbach@chromium.org __ mov(ebx, masm->isolate()->factory()->undefined_value()); 11041510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ArrayConstructorStub stub(masm->isolate()); 11051510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ TailCallStub(&stub); 11062bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com} 11072bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 11082bc58ef330b2d92ba287754282872699c151db4achristian.plesner.hansen@gmail.com 1109d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.orgvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) { 1110d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------- S t a t e ------------- 1111d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- eax : number of arguments 1112d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- edi : constructor function 1113d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[0] : return address 1114d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1115d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[(argc + 1) * 4] : receiver 1116d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------------------------------- 11177979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Counters* counters = masm->isolate()->counters(); 11187979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_calls(), 1); 1119d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1120d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org if (FLAG_debug_code) { 1121d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); 1122c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(edi, ecx); 1123594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedStringFunction); 1124d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org } 1125d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1126d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Load the first argument into eax and get rid of the rest 1127d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // (including the receiver). 1128d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label no_arguments; 1129c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(eax, eax); 1130d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ j(zero, &no_arguments); 1131d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); 1132d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ pop(ecx); 1133d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); 1134d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ push(ecx); 1135d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(eax, ebx); 1136d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1137d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Lookup the argument in the number to string cache. 1138d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label not_cached, argument_is_string; 1139528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ LookupNumberStringCache(eax, // Input. 1140528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ebx, // Result. 1141528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ecx, // Scratch 1. 1142528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org edx, // Scratch 2. 1143528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ¬_cached); 11447979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_cached_number(), 1); 1145d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&argument_is_string); 1146d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------- S t a t e ------------- 1147d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- ebx : argument converted to string 1148d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- edi : constructor function 1149d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // -- esp[0] : return address 1150d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // ----------------------------------- 1151d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1152d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Allocate a JSValue and put the tagged pointer into eax. 1153d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label gc_required; 11542bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org __ Allocate(JSValue::kSize, 11552bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org eax, // Result. 11562bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org ecx, // New allocation top (we ignore it). 11572bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org no_reg, 11582bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org &gc_required, 11592bda543d75374afd8d7e98f56ca99a57ae1b7bd1svenpanne@chromium.org TAG_OBJECT); 1160d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1161d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Set the map. 1162d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ LoadGlobalFunctionInitialMap(edi, ecx); 1163d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org if (FLAG_debug_code) { 1164d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), 1165d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org JSValue::kSize >> kPointerSizeLog2); 1166594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedStringWrapperInstanceSize); 1167d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); 1168594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(equal, kUnexpectedUnusedPropertiesOfStringWrapper); 1169d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org } 1170d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); 1171d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1172d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Set properties and elements. 11737979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org Factory* factory = masm->isolate()->factory(); 1174a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(ecx, Immediate(factory->empty_fixed_array())); 1175d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); 1176d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); 1177d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1178d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Set the value. 1179d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); 1180d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1181d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Ensure the object is fully initialized. 1182d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); 1183d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1184d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // We're done. Return. 1185d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ ret(0); 1186d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1187d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // The argument was not found in the number to string cache. Check 1188d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // if it's a string already before calling the conversion builtin. 1189d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Label convert_argument; 1190d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(¬_cached); 1191d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org STATIC_ASSERT(kSmiTag == 0); 11927b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org __ JumpIfSmi(eax, &convert_argument); 1193d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); 1194d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ j(NegateCondition(is_string), &convert_argument); 1195d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(ebx, eax); 11967979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_string_value(), 1); 1197d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ jmp(&argument_is_string); 1198d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1199d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Invoke the conversion builtin and put the result into ebx. 1200d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&convert_argument); 12017979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_conversions(), 1); 1202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1203c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 1204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(edi); // Preserve the function. 1205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 1206c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 1207c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(edi); 1208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1209d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ mov(ebx, eax); 1210d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ jmp(&argument_is_string); 1211d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1212d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // Load the empty string into ebx, remove the receiver from the 1213d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // stack, and jump back to the case where the argument is a string. 1214d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&no_arguments); 1215a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org __ Move(ebx, Immediate(factory->empty_string())); 1216d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ pop(ecx); 1217d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ lea(esp, Operand(esp, kPointerSize)); 1218d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ push(ecx); 1219d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ jmp(&argument_is_string); 1220d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1221d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // At this point the argument is already a string. Call runtime to 1222d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org // create a string wrapper. 1223d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ bind(&gc_required); 12247979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(counters->string_ctor_gc_required(), 1); 1225c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 1227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(ebx); 1228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kNewStringWrapper, 1); 1229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1230d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org __ ret(0); 1231d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org} 1232d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1233d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org 1234e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.orgstatic void ArgumentsAdaptorStackCheck(MacroAssembler* masm, 1235e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org Label* stack_overflow) { 1236e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // ----------- S t a t e ------------- 1237e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // -- eax : actual number of arguments 1238e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // -- ebx : expected number of arguments 1239e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // -- edi : function (passed through to callee) 1240e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // ----------------------------------- 1241e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // Check the stack for overflow. We are not trying to catch 1242e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // interruptions (e.g. debug break and preemption) here, so the "real stack 1243e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // limit" is checked. 1244e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org ExternalReference real_stack_limit = 1245e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org ExternalReference::address_of_real_stack_limit(masm->isolate()); 1246e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ mov(edx, Operand::StaticVariable(real_stack_limit)); 1247e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // Make ecx the space we have left. The stack might already be overflowed 1248e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // here which will cause ecx to become negative. 1249e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ mov(ecx, esp); 1250e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ sub(ecx, edx); 1251e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // Make edx the space we need for the array when it is unrolled onto the 1252e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // stack. 1253e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ mov(edx, ebx); 1254e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ shl(edx, kPointerSizeLog2); 1255e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org // Check if the arguments will overflow the stack. 1256e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ cmp(ecx, edx); 1257e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ j(less_equal, stack_overflow); // Signed comparison. 1258e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org} 1259e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 1260e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 126143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 126243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(ebp); 1263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(ebp, esp); 126443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 126543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Store the arguments adaptor context sentinel. 126618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org __ push(Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 126743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 126843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Push the function on the stack. 126943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(edi); 127043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 127140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Preserve the number of arguments on the stack. Must preserve eax, 127240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // ebx and ecx because these registers are used when copying the 127343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // arguments and the receiver. 127480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kSmiTagSize == 1); 127540cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ lea(edi, Operand(eax, eax, times_1, kSmiTag)); 127640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ push(edi); 127743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 127843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 127943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 12807c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.orgstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 128143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Retrieve the number of arguments from the stack. 128243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); 128343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 128443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Leave the frame. 128543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ leave(); 128643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 128743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Remove caller arguments from the stack. 128880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 128943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ pop(ecx); 129043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver 129143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(ecx); 129243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 129343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 129443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 129543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 129643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ----------- S t a t e ------------- 129743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // -- eax : actual number of arguments 129843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // -- ebx : expected number of arguments 129926ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org // -- edi : function (passed through to callee) 130043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ----------------------------------- 130143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1302b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org Label invoke, dont_adapt_arguments; 13037979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1); 130443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1305e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org Label stack_overflow; 1306e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org ArgumentsAdaptorStackCheck(masm, &stack_overflow); 1307e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 130843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label enough, too_few; 130926ca35cc4ec47151d9c6d3890b0f052fc79cb8afmachenbach@chromium.org __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); 1310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ebx); 131143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ j(less, &too_few); 1312b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); 1313b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ j(equal, &dont_adapt_arguments); 131443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 131543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen { // Enough parameters: Actual >= expected. 131643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&enough); 131743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen EnterArgumentsAdaptorFrame(masm); 131843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 131943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Copy receiver and all expected arguments. 132043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const int offset = StandardFrameConstants::kCallerSPOffset; 132143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(eax, Operand(ebp, eax, times_4, offset)); 132240cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ mov(edi, -1); // account for receiver 132343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 132443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label copy; 132543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(©); 132640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ inc(edi); 132743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(Operand(eax, 0)); 1328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(eax, Immediate(kPointerSize)); 1329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(edi, ebx); 133043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ j(less, ©); 133143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ jmp(&invoke); 133243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 133343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 133443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen { // Too few parameters: Actual < expected. 133543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&too_few); 133643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen EnterArgumentsAdaptorFrame(masm); 133743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 133843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Copy receiver and all actual arguments. 133943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen const int offset = StandardFrameConstants::kCallerSPOffset; 134043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ lea(edi, Operand(ebp, eax, times_4, offset)); 134140cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // ebx = expected - actual. 1342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(ebx, eax); 134340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // eax = -actual - 1 134440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ neg(eax); 1345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(eax, Immediate(1)); 134643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 134743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label copy; 134843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(©); 134940cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ inc(eax); 135043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ push(Operand(edi, 0)); 1351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sub(edi, Immediate(kPointerSize)); 1352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ test(eax, eax); 135340cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ j(not_zero, ©); 135443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 135543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Fill remaining expected arguments with undefined values. 135643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Label fill; 135743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&fill); 135840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ inc(eax); 13597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org __ push(Immediate(masm->isolate()->factory()->undefined_value())); 1360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ cmp(eax, ebx); 136143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ j(less, &fill); 136243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 136343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1364b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // Call the entry point. 136543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ bind(&invoke); 136640cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Restore function pointer. 136740cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ call(edx); 136943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1370967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org // Store offset of return address for deoptimizer. 1371659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 1372967e270a034432457500dbf950d2c4951a929e52ulan@chromium.org 13737c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org // Leave frame and return. 13747c537e2abe09729ed6cb827b4dd206470d8c4a42ager@chromium.org LeaveArgumentsAdaptorFrame(masm); 137543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen __ ret(0); 137643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 137743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ------------------------------------------- 1378b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org // Dont adapt arguments. 137943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // ------------------------------------------- 1380b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org __ bind(&dont_adapt_arguments); 1381c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(edx); 1382e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org 1383e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ bind(&stack_overflow); 1384e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org { 1385e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org FrameScope frame(masm, StackFrame::MANUAL); 1386e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org EnterArgumentsAdaptorFrame(masm); 1387e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 1388e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org __ int3(); 1389e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org } 139043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 139143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 139243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1393a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1394e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org // Lookup the function in the JavaScript frame. 1395a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 1396c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 1398afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org // Pass function as argument. 1399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(eax); 1400afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); 1401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1402a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 140383a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org Label skip; 1404c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // If the code object is null, just return to the unoptimized code. 1405c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ cmp(eax, Immediate(0)); 140683a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org __ j(not_equal, &skip, Label::kNear); 1407a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ ret(0); 1408a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1409a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org __ bind(&skip); 1410c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1411c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Load deoptimization data from the code object. 1412c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ mov(ebx, Operand(eax, Code::kDeoptimizationDataOffset - kHeapObjectTag)); 1413c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1414c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Load the OSR entrypoint offset from the deoptimization data. 1415c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ mov(ebx, Operand(ebx, FixedArray::OffsetOfElementAt( 1416c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag)); 1417c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ SmiUntag(ebx); 1418c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1419c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Compute the target address = code_obj + header_size + osr_offset 1420c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ lea(eax, Operand(eax, ebx, times_1, Code::kHeaderSize - kHeapObjectTag)); 1421c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1422c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Overwrite the return address on the stack. 1423c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ mov(Operand(esp, 0), eax); 1424c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1425c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // And "return" to the OSR entry point of the function. 1426c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ ret(0); 1427a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 1428a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 1429a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 14308e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.orgvoid Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) { 14318e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org // We check the stack limit as indicator that recompilation might be done. 14328e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org Label ok; 14338e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org ExternalReference stack_limit = 14348e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org ExternalReference::address_of_stack_limit(masm->isolate()); 14358e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ cmp(esp, Operand::StaticVariable(stack_limit)); 14368e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ j(above_equal, &ok, Label::kNear); 14378e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org { 14388e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 1439895f00d1d8c5a7a7209c36d690688e3552de3df4machenbach@chromium.org __ CallRuntime(Runtime::kHiddenStackGuard, 0); 14408e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org } 14418e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ jmp(masm->isolate()->builtins()->OnStackReplacement(), 14428e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org RelocInfo::CODE_TARGET); 14438e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org 14448e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ bind(&ok); 14458e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ ret(0); 14468e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org} 14478e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org 144843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#undef __ 14497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org} 14507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org} // namespace v8::internal 14519dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com 14529dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif // V8_TARGET_ARCH_IA32 1453