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