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, &not_no_registers, Label::kNear);
713a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ret(1 * kPointerSize);  // Remove state.
714a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
715a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&not_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, &not_tos_eax, Label::kNear);
719a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ret(2 * kPointerSize);  // Remove state, eax.
720a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
721a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&not_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                             &not_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(&not_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(&copy);
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, &copy);
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(&copy);
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, &copy);
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