1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/handler-compiler.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/jsregexp.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/regexp-macro-assembler.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/runtime.h"
1880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
2180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InitializeArrayConstructorDescriptor(
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate, CodeStubDescriptor* descriptor,
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int constant_stack_parameter_count) {
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address deopt_handler = Runtime::FunctionForId(
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Runtime::kArrayConstructor)->entry;
2880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (constant_stack_parameter_count == 0) {
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           JS_FUNCTION_STUB_MODE);
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    descriptor->Initialize(rax, deopt_handler, constant_stack_parameter_count,
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS);
3580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
3680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
3780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void InitializeInternalArrayConstructorDescriptor(
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate, CodeStubDescriptor* descriptor,
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int constant_stack_parameter_count) {
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address deopt_handler = Runtime::FunctionForId(
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Runtime::kInternalArrayConstructor)->entry;
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (constant_stack_parameter_count == 0) {
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           JS_FUNCTION_STUB_MODE);
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    descriptor->Initialize(rax, deopt_handler, constant_stack_parameter_count,
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS);
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayNoArgumentConstructorStub::InitializeDescriptor(
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeStubDescriptor* descriptor) {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArraySingleArgumentConstructorStub::InitializeDescriptor(
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeStubDescriptor* descriptor) {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
65592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
66592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayNArgumentsConstructorStub::InitializeDescriptor(
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeStubDescriptor* descriptor) {
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
7080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
7180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
7280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeStubDescriptor* descriptor) {
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeStubDescriptor* descriptor) {
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeStubDescriptor* descriptor) {
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
8969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
9080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm)
9280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               ExternalReference miss) {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update the static counter each time a new code stub is generated.
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate()->counters()->code_stubs()->Increment();
9880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor();
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int param_count = descriptor.GetEnvironmentParameterCount();
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Call the runtime system in a fresh internal frame.
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(param_count == 0 ||
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           rax.is(descriptor.GetEnvironmentParameterRegister(param_count - 1)));
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push arguments
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < param_count; ++i) {
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(descriptor.GetEnvironmentParameterRegister(i));
10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallExternalReference(miss, param_count);
11169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
11280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
11469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
11580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
11669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushCallerSaved(save_doubles() ? kSaveFPRegs : kDontSaveFPRegs);
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int argument_count = 1;
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PrepareCallCFunction(argument_count);
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadAddress(arg_reg_1,
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 ExternalReference::isolate_address(isolate()));
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AllowExternalCallThatCantCauseGC scope(masm);
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallCFunction(
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::store_buffer_overflow_function(isolate()),
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      argument_count);
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopCallerSaved(save_doubles() ? kSaveFPRegs : kDontSaveFPRegs);
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenclass FloatingPointHelper : public AllStatic {
13480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen public:
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum ConvertUndefined {
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CONVERT_UNDEFINED_TO_ZERO,
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BAILOUT_ON_UNDEFINED
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
13980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the operands from rdx and rax into xmm0 and xmm1, as doubles.
14080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If the operands are not both numbers, jump to not_numbers.
14180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Leaves rdx and rax unchanged.  SmiOperands assumes both are smis.
14280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // NumberOperands assumes both are smis or heap numbers.
14380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static void LoadSSE2UnknownOperands(MacroAssembler* masm,
14480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                      Label* not_numbers);
1458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch};
14680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
14780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid DoubleToIStub::Generate(MacroAssembler* masm) {
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register input_reg = this->source();
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register final_result_reg = this->destination();
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(is_truncating());
1523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label check_negative, process_64_bits, done;
154086aeeaae12517475c22695a200be45495516549Ben Murdoch
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int double_offset = offset();
1561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Account for return address and saved regs if input is rsp.
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (input_reg.is(rsp)) double_offset += 3 * kRegisterSize;
159086aeeaae12517475c22695a200be45495516549Ben Murdoch
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand mantissa_operand(MemOperand(input_reg, double_offset));
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemOperand exponent_operand(MemOperand(input_reg,
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           double_offset + kDoubleSize / 2));
1631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch1;
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch_candidates[3] = { rbx, rdx, rdi };
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < 3; i++) {
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      scratch1 = scratch_candidates[i];
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break;
1698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
1701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Since we must use rcx for shifts below, use some other register (rax)
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to calculate the result if ecx is the requested return register.
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register result_reg = final_result_reg.is(rcx) ? rax : final_result_reg;
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save ecx if it isn't the return register and therefore volatile, or if it
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is the return register, then save the temp register we use in its stead
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // for the result.
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register save_reg = final_result_reg.is(rcx) ? rax : rcx;
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(scratch1);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(save_reg);
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool stash_exponent_copy = !input_reg.is(rsp);
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movl(scratch1, mantissa_operand);
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(xmm0, mantissa_operand);
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movl(rcx, exponent_operand);
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (stash_exponent_copy) __ pushq(rcx);
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andl(rcx, Immediate(HeapNumber::kExponentMask));
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ shrl(rcx, Immediate(HeapNumber::kExponentShift));
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leal(result_reg, MemOperand(rcx, -HeapNumber::kExponentBias));
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpl(result_reg, Immediate(HeapNumber::kMantissaBits));
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(below, &process_64_bits);
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Result is entirely in lower 32-bits of mantissa
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subl(rcx, Immediate(delta));
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ xorl(result_reg, result_reg);
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpl(rcx, Immediate(31));
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(above, &done);
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ shll_cl(scratch1);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&check_negative);
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&process_64_bits);
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cvttsd2siq(result_reg, xmm0);
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kNear);
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If the double was negative, negate the integer result.
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&check_negative);
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movl(result_reg, scratch1);
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ negl(result_reg);
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (stash_exponent_copy) {
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmpl(MemOperand(rsp, 0), Immediate(0));
2128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    } else {
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ cmpl(exponent_operand, Immediate(0));
2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmovl(greater, result_reg, scratch1);
21680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Restore registers
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (stash_exponent_copy) {
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ addp(rsp, Immediate(kDoubleSize));
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!final_result_reg.is(result_reg)) {
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(final_result_reg.is(rcx));
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movl(final_result_reg, result_reg);
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ popq(save_reg);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ popq(scratch1);
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ret(0);
22980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
23080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
23280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm,
23380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                                  Label* not_numbers) {
23480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done;
23580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load operand in rdx into xmm0, or branch to not_numbers.
23680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex);
23780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfSmi(rdx, &load_smi_rdx);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(FieldOperand(rdx, HeapObject::kMapOffset), rcx);
23980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_equal, not_numbers);  // Argument in rdx is not a number.
24080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
24180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load operand in rax into xmm1, or branch to not_numbers.
24280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfSmi(rax, &load_smi_rax);
24380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&load_nonsmi_rax);
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(FieldOperand(rax, HeapObject::kMapOffset), rcx);
24680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_equal, not_numbers);
24780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
24880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&done);
24980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&load_smi_rdx);
25180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ SmiToInteger32(kScratchRegister, rdx);
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cvtlsi2sd(xmm0, kScratchRegister);
25380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfNotSmi(rax, &load_nonsmi_rax);
25480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
25580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&load_smi_rax);
25680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ SmiToInteger32(kScratchRegister, rax);
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cvtlsi2sd(xmm1, kScratchRegister);
25880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
25980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
26080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid MathPowStub::Generate(MacroAssembler* masm) {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Register exponent = MathPowTaggedDescriptor::exponent();
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(exponent.is(rdx));
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register base = rax;
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Register scratch = rcx;
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const XMMRegister double_result = xmm3;
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const XMMRegister double_base = xmm2;
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const XMMRegister double_exponent = xmm1;
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const XMMRegister double_scratch = xmm4;
271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label call_runtime, done, exponent_not_smi, int_exponent;
273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Save 1 in double_result - we need this several times later on.
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, Immediate(1));
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cvtlsi2sd(double_result, scratch);
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (exponent_type() == ON_STACK) {
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label base_is_smi, unpack_exponent;
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The exponent and base are supplied as arguments on the stack.
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // This can only happen if the stub is called from non-optimized code.
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Load input parameters from stack.
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(base, args.GetArgumentOperand(0));
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(exponent, args.GetArgumentOperand(1));
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfSmi(base, &base_is_smi, Label::kNear);
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset),
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Heap::kHeapNumberMapRootIndex);
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &call_runtime);
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset));
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&unpack_exponent, Label::kNear);
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&base_is_smi);
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiToInteger32(base, base);
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cvtlsi2sd(double_base, base);
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&unpack_exponent);
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiToInteger32(exponent, exponent);
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&int_exponent);
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&exponent_not_smi);
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset),
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   Heap::kHeapNumberMapRootIndex);
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &call_runtime);
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset));
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (exponent_type() == TAGGED) {
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ SmiToInteger32(exponent, exponent);
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&int_exponent);
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&exponent_not_smi);
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(double_exponent, FieldOperand(exponent, HeapNumber::kValueOffset));
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (exponent_type() != INTEGER) {
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label fast_power, try_arithmetic_simplification;
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Detect integer exponents stored as double.
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ DoubleToI(exponent, double_exponent, double_scratch,
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification,
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 &try_arithmetic_simplification,
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 &try_arithmetic_simplification);
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&int_exponent);
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&try_arithmetic_simplification);
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ cvttsd2si(exponent, double_exponent);
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip to runtime if possibly NaN (indicated by the indefinite integer).
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpl(exponent, Immediate(0x1));
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(overflow, &call_runtime);
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (exponent_type() == ON_STACK) {
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Detect square root case.  Crankshaft detects constant +/-0.5 at
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // compile time and uses DoMathPowHalf instead.  We then skip this check
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // for non-constant cases of +/-0.5 as these hardly occur.
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Label continue_sqrt, continue_rsqrt, not_plus_half;
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Test for 0.5.
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Load double_scratch with 0.5.
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(scratch, V8_UINT64_C(0x3FE0000000000000));
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(double_scratch, scratch);
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Already ruled out NaNs for exponent.
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ucomisd(double_scratch, double_exponent);
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &not_plus_half, Label::kNear);
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Calculates square root of base.  Check for the special case of
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // According to IEEE-754, double-precision -Infinity has the highest
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // 12 bits set and the lowest 52 bits cleared.
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(scratch, V8_UINT64_C(0xFFF0000000000000));
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(double_scratch, scratch);
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ucomisd(double_scratch, double_base);
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Comparing -Infinity with NaN results in "unordered", which sets the
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // zero flag as if both were equal.  However, it also sets the carry flag.
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &continue_sqrt, Label::kNear);
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(carry, &continue_sqrt, Label::kNear);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Set result to Infinity in the special case.
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ xorps(double_result, double_result);
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ subsd(double_result, double_scratch);
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&continue_sqrt);
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ xorps(double_scratch, double_scratch);
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addsd(double_scratch, double_base);  // Convert -0 to 0.
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sqrtsd(double_result, double_scratch);
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Test for -0.5.
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&not_plus_half);
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Load double_scratch with -0.5 by substracting 1.
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ subsd(double_scratch, double_result);
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Already ruled out NaNs for exponent.
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ucomisd(double_scratch, double_exponent);
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &fast_power, Label::kNear);
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Calculates reciprocal of square root of base.  Check for the special
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // According to IEEE-754, double-precision -Infinity has the highest
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // 12 bits set and the lowest 52 bits cleared.
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movq(scratch, V8_UINT64_C(0xFFF0000000000000));
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ movq(double_scratch, scratch);
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ ucomisd(double_scratch, double_base);
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Comparing -Infinity with NaN results in "unordered", which sets the
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // zero flag as if both were equal.  However, it also sets the carry flag.
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(not_equal, &continue_rsqrt, Label::kNear);
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ j(carry, &continue_rsqrt, Label::kNear);
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Set result to 0 in the special case.
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ xorps(double_result, double_result);
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ bind(&continue_rsqrt);
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ xorps(double_exponent, double_exponent);
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ addsd(double_exponent, double_base);  // Convert -0 to +0.
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ sqrtsd(double_exponent, double_exponent);
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ divsd(double_result, double_exponent);
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ jmp(&done);
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
40185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Using FPU instructions to calculate power.
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label fast_power_failed;
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&fast_power);
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fnclex();  // Clear flags to catch exceptions later.
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Transfer (B)ase and (E)xponent onto the FPU register stack.
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subp(rsp, Immediate(kDoubleSize));
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(Operand(rsp, 0), double_exponent);
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fld_d(Operand(rsp, 0));  // E
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(Operand(rsp, 0), double_base);
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fld_d(Operand(rsp, 0));  // B, E
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Exponent is in st(1) and base is in st(0)
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B)
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FYL2X calculates st(1) * log2(st(0))
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fyl2x();    // X
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fld(0);     // X, X
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ frndint();  // rnd(X), X
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fsub(1);    // rnd(X), X-rnd(X)
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fxch(1);    // X - rnd(X), rnd(X)
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ f2xm1();    // 2^(X-rnd(X)) - 1, rnd(X)
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fld1();     // 1, 2^(X-rnd(X)) - 1, rnd(X)
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ faddp(1);   // 2^(X-rnd(X)), rnd(X)
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FSCALE calculates st(0) * 2^st(1)
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fscale();   // 2^X, rnd(X)
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fstp(1);
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Bail out to runtime in case of exceptions in the status word.
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fnstsw_ax();
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ testb(rax, Immediate(0x5F));  // Check for all but precision exception.
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_zero, &fast_power_failed, Label::kNear);
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fstp_d(Operand(rsp, 0));
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(double_result, Operand(rsp, 0));
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addp(rsp, Immediate(kDoubleSize));
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&done);
436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&fast_power_failed);
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ fninit();
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ addp(rsp, Immediate(kDoubleSize));
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&call_runtime);
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
44285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Calculate power with integer exponent.
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&int_exponent);
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const XMMRegister double_scratch2 = double_exponent;
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Back up exponent as we need to check if exponent is negative later.
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, exponent);  // Back up exponent.
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movsd(double_scratch, double_base);  // Back up base.
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movsd(double_scratch2, double_result);  // Load double_exponent with 1.
450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get absolute value of exponent.
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_neg, while_true, while_false;
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testl(scratch, scratch);
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(positive, &no_neg, Label::kNear);
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ negl(scratch);
456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&no_neg);
457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &while_false, Label::kNear);
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ shrl(scratch, Immediate(1));
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Above condition means CF==0 && ZF==0.  This means that the
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bit that has been shifted out is 0 and the result is not 0.
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(above, &while_true, Label::kNear);
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movsd(double_result, double_scratch);
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &while_false, Label::kNear);
465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&while_true);
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ shrl(scratch, Immediate(1));
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ mulsd(double_scratch, double_scratch);
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(above, &while_true, Label::kNear);
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mulsd(double_result, double_scratch);
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_zero, &while_true);
47285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&while_false);
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the exponent is negative, return 1/result.
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testl(exponent, exponent);
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(greater, &done);
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ divsd(double_scratch2, double_result);
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movsd(double_result, double_scratch2);
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Test whether result is zero.  Bail out to check for subnormal result.
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ xorps(double_scratch2, double_scratch2);
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ucomisd(double_scratch2, double_result);
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // double_exponent aliased as double_scratch2 has already been overwritten
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and may not have contained the exponent value in the first place when the
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // input was a smi.  We reset it with exponent value before bailing out.
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &done);
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cvtlsi2sd(double_exponent, exponent);
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returning or bailing out.
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Counters* counters = isolate()->counters();
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (exponent_type() == ON_STACK) {
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The arguments are still on the stack.
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&call_runtime);
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TailCallRuntime(Runtime::kMathPowRT, 2, 1);
49585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The stub is called from non-optimized code, which expects the result
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // as heap number in rax.
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateHeapNumber(rax, rcx, &call_runtime);
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result);
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ IncrementCounter(counters->math_pow(), 1);
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(2 * kPointerSize);
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&call_runtime);
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Move base to the correct argument register.  Exponent is already in xmm1.
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(xmm0, double_base);
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(double_exponent.is(xmm1));
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    {
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AllowExternalCallThatCantCauseGC scope(masm);
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ PrepareCallCFunction(2);
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      __ CallCFunction(
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ExternalReference::power_double_double_function(isolate()), 2);
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Return value is in xmm0.
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movsd(double_result, xmm0);
51685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&done);
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ IncrementCounter(counters->math_pow(), 1);
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FunctionPrototypeStub::Generate(MacroAssembler* masm) {
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label miss;
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register receiver = LoadDescriptor::ReceiverRegister();
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8,
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                          r9, &miss);
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&miss);
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PropertyAccessCompiler::TailCallBuiltin(
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
53780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The key is in rdx and the parameter count is in rax.
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rdx.is(ArgumentsAccessReadDescriptor::index()));
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(rax.is(ArgumentsAccessReadDescriptor::parameter_count()));
54080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
54180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the key is a smi.
54280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label slow;
54380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfNotSmi(rdx, &slow);
54480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Check if the calling frame is an arguments adaptor frame.  We look at the
54644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // context offset, and if the frame is not a regular one, then we find a
54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Smi instead of the context.  We can't use SmiCompare here, because that
54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // only works for comparing two smis.
54980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label adaptor;
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
55244f0eee88ff00398ff7f715fab053374d808c90dSteve Block         Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
55380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(equal, &adaptor);
55480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
55580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check index against formal parameters count limit passed in
55680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // through register rax. Use unsigned comparison to get negative
55780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // check for free.
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rdx, rax);
55980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(above_equal, &slow);
56080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
56180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Read the argument from the stack and return it.
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiSub(rax, rax, rdx);
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rax, rax);
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rbp, rax, ARGUMENTS_DONT_CONTAIN_RECEIVER);
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, args.GetArgumentOperand(0));
56680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
56780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
56880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Arguments adaptor case: Check index against actual arguments
56980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // limit found in the arguments adaptor frame. Use unsigned
57080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // comparison to get negative check for free.
57180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&adaptor);
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rdx, rcx);
57480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(above_equal, &slow);
57580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
57680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Read the argument from the stack and return it.
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiSub(rcx, rcx, rdx);
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rcx, rcx);
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor adaptor_args(rbx, rcx,
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      ARGUMENTS_DONT_CONTAIN_RECEIVER);
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, adaptor_args.GetArgumentOperand(0));
58280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Ret();
58380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
58480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Slow-case: Handle non-smi or out-of-bounds access to arguments
58580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // by calling the runtime system.
58680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&slow);
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(rbx);
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(rbx);
59080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
59180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
59280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
59380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Stack layout:
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[0]  : return address
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[8]  : number of parameters (tagged)
5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  rsp[16] : receiver displacement
5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  rsp[24] : function
6003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Registers used over the whole function:
6013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  rbx: the mapped parameter count (untagged)
6023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //  rax: the allocated object (tagged).
6033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
6053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger64(rbx, args.GetArgumentOperand(2));
6083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rbx = parameter count (untagged)
6093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if the calling frame is an arguments adaptor frame.
6113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label runtime;
6123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label adaptor_frame, try_allocate;
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
6153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
6163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(equal, &adaptor_frame);
6173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // No adaptor, parameter count = argument count.
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, rbx);
6203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(&try_allocate, Label::kNear);
6213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We have an adaptor frame. Patch the parameters pointer.
6233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&adaptor_frame);
6243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(rcx,
6253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                    Operand(rdx,
6263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            ArgumentsAdaptorFrameConstants::kLengthOffset));
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdx, Operand(rdx, rcx, times_pointer_size,
6283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      StandardFrameConstants::kCallerSPOffset));
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args.GetArgumentOperand(1), rdx);
6303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rbx = parameter count (untagged)
6323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx = argument count (untagged)
6333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute the mapped parameter count = min(rbx, rcx) in rbx.
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rbx, rcx);
6353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(less_equal, &try_allocate, Label::kNear);
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, rcx);
6373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&try_allocate);
6393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Compute the sizes of backing store, parameter map, and arguments object.
6413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 1. Parameter map, has 2 extra words containing context and backing store.
6423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int kParameterMapHeaderSize =
6433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      FixedArray::kHeaderSize + 2 * kPointerSize;
6443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label no_parameter_map;
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ xorp(r8, r8);
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rbx, rbx);
6473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(zero, &no_parameter_map, Label::kNear);
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize));
6493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&no_parameter_map);
6503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 2. Backing store.
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize));
6533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // 3. Arguments object.
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r8, Immediate(Heap::kSloppyArgumentsObjectSize));
6563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Do the allocation of all three objects in one go.
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
6593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rax = address of new object(s) (tagged)
6613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx = argument count (untagged)
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the arguments map from the current native context into rdi.
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label has_mapped_parameters, instantiate;
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset));
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rbx, rbx);
6673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(not_zero, &has_mapped_parameters, Label::kNear);
6683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX;
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex)));
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&instantiate, Label::kNear);
6723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kAliasedIndex = Context::ALIASED_ARGUMENTS_MAP_INDEX;
6743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&has_mapped_parameters);
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex)));
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&instantiate);
6773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rax = address of new object (tagged)
6793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rbx = mapped parameter count (untagged)
6803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx = argument count (untagged)
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi = address of arguments map (tagged)
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi);
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister);
6863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the callee in-object property.
6883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, args.GetArgumentOperand(0));
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertNotSmi(rdx);
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kHeaderSize +
6923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       Heap::kArgumentsCalleeIndex * kPointerSize),
6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          rdx);
6943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Use the length (smi tagged) and set that as an in-object property too.
6963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Note: rcx is tagged from here on.
6973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
6983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Integer32ToSmi(rcx, rcx);
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kHeaderSize +
7003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       Heap::kArgumentsLengthIndex * kPointerSize),
7013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          rcx);
7023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the elements pointer in the allocated arguments object.
7043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If we allocated a parameter map, edi will point there, otherwise to the
7053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // backing store.
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize));
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
7083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rax = address of new object (tagged)
7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rbx = mapped parameter count (untagged)
7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx = argument count (tagged)
7123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rdi = address of parameter map or backing store (tagged)
7133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Initialize parameter map. If there are no mapped arguments, we're done.
7153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label skip_parameter_map;
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rbx, rbx);
7173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(zero, &skip_parameter_map);
7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex);
7203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rbx contains the untagged argument count. Add 2 and tag to write.
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Integer64PlusConstantToSmi(r9, rbx, 2);
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9);
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi);
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9);
7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Copy the parameter slots and the holes in the arguments.
7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We need to fill in mapped_parameter_count slots. They index the context,
7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // where parameters are stored in reverse order, at
7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //   MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The mapped parameter thus need to get indices
7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //   MIN_CONTEXT_SLOTS+parameter_count-1 ..
7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //       MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We loop from right to left.
7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label parameters_loop, parameters_test;
7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Load tagged parameter count into r9.
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Integer32ToSmi(r9, rbx);
7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS));
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r8, args.GetArgumentOperand(2));
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(r8, r9);
7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Move(r11, factory->the_hole_value());
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, rdi);
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r9 = loop variable (tagged)
7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r8 = mapping index (tagged)
7483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // r11 = the hole value
7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rdx = address of parameter map (tagged)
7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rdi = address of backing store (tagged)
7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(&parameters_test, Label::kNear);
7523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&parameters_loop);
7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiSubConstant(r9, r9, Smi::FromInt(1));
7553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(kScratchRegister, r9);
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdx, kScratchRegister,
7573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       times_pointer_size,
7583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       kParameterMapHeaderSize),
7593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          r8);
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, kScratchRegister,
7613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       times_pointer_size,
7623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       FixedArray::kHeaderSize),
7633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          r11);
7643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiAddConstant(r8, r8, Smi::FromInt(1));
7653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&parameters_test);
7663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiTest(r9);
7673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(not_zero, &parameters_loop, Label::kNear);
7683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&skip_parameter_map);
7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx = argument count (tagged)
7723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rdi = address of backing store (tagged)
7733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Copy arguments header and remaining slots (if there are any).
7743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Move(FieldOperand(rdi, FixedArray::kMapOffset),
7753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          factory->fixed_array_map());
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
7773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label arguments_loop, arguments_test;
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r8, rbx);
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, args.GetArgumentOperand(1));
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Untag rcx for the loop below.
7823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(rcx, rcx);
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(kScratchRegister, Operand(r8, times_pointer_size, 0));
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, kScratchRegister);
7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ jmp(&arguments_test, Label::kNear);
7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&arguments_loop);
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, Immediate(kPointerSize));
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r9, Operand(rdx, 0));
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, r8,
7913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       times_pointer_size,
7923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       FixedArray::kHeaderSize),
7933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          r9);
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r8, Immediate(1));
7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&arguments_test);
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(r8, rcx);
7983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(less, &arguments_loop, Label::kNear);
7993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Return and remove the on-stack parameters.
8013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ ret(3 * kPointerSize);
8023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Do the runtime call to allocate the arguments object.
8043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // rcx = argument count (untagged)
8053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&runtime);
8063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Integer32ToSmi(rcx, rcx);
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args.GetArgumentOperand(2), rcx);  // Patch argument count.
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
8093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[0]  : return address
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[8]  : number of parameters
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[16] : receiver displacement
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[24] : function
8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if the calling frame is an arguments adaptor frame.
8193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label runtime;
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
8223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(not_equal, &runtime);
8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Patch the arguments.length and the parameters pointer.
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args.GetArgumentOperand(2), rcx);
8293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(rcx, rcx);
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdx, Operand(rdx, rcx, times_pointer_size,
8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              StandardFrameConstants::kCallerSPOffset));
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args.GetArgumentOperand(1), rdx);
8333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&runtime);
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return address is on the stack.
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label slow;
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register receiver = LoadDescriptor::ReceiverRegister();
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register key = LoadDescriptor::NameRegister();
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = rax;
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!scratch.is(receiver) && !scratch.is(key));
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the key is an array index, that is Uint32.
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiValueSize <= 32);
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpUnlessNonNegativeSmi(key, &slow);
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Everything is fine, call runtime.
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(scratch);
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(receiver);  // receiver
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(key);       // key
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(scratch);
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Perform tail call to the entry.
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallExternalReference(
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor),
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        masm->isolate()),
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      2, 1);
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&slow);
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PropertyAccessCompiler::TailCallBuiltin(
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[0]  : return address
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[8]  : number of parameters
87380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rsp[16] : receiver displacement
87480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rsp[24] : function
87580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
87680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check if the calling frame is an arguments adaptor frame.
87780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label adaptor_frame, try_allocate, runtime;
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
8803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
88180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(equal, &adaptor_frame);
88280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
88380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Get the length from the frame.
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, args.GetArgumentOperand(2));
8863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(rcx, rcx);
88780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&try_allocate);
88880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
88980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Patch the arguments.length and the parameters pointer.
89080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&adaptor_frame);
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args.GetArgumentOperand(2), rcx);
8933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(rcx, rcx);
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdx, Operand(rdx, rcx, times_pointer_size,
8953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      StandardFrameConstants::kCallerSPOffset));
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args.GetArgumentOperand(1), rdx);
89780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
89880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Try the new space allocation. Start out with computing the size of
89980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the arguments object and the elements array.
90080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label add_arguments_object;
90180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&try_allocate);
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rcx, rcx);
9033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ j(zero, &add_arguments_object, Label::kNear);
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
90580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&add_arguments_object);
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rcx, Immediate(Heap::kStrictArgumentsObjectSize));
90780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
90880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do the allocation of both objects in one go.
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the arguments map from the current native context.
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset));
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX);
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, Operand(rdi, offset));
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi);
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex);
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister);
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister);
92180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
92280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Get the length (smi tagged) and set that as an in-object property too.
9233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, args.GetArgumentOperand(2));
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kHeaderSize +
9263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                       Heap::kArgumentsLengthIndex * kPointerSize),
92744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          rcx);
92880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
92980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If there are no actual arguments, we're done.
93080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label done;
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rcx, rcx);
93280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &done);
93380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Get the parameters pointer from the stack.
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, args.GetArgumentOperand(1));
93680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the elements pointer in the allocated arguments object and
93880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // initialize the header in the elements fixed array.
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize));
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
94180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
9463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Untag the length for the loop below.
9473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ SmiToInteger64(rcx, rcx);
94880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
94980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Copy the fixed array slots.
95080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label loop;
95180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&loop);
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, Operand(rdx, -1 * kPointerSize));  // Skip receiver.
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rdi, FixedArray::kHeaderSize), rbx);
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rdi, Immediate(kPointerSize));
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, Immediate(kPointerSize));
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ decp(rcx);
95780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_zero, &loop);
95880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
95980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return and remove the on-stack parameters.
96080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
96180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret(3 * kPointerSize);
96280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
96380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Do the runtime call to allocate the arguments object.
96480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&runtime);
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
96680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
96780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
96880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
96980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid RegExpExecStub::Generate(MacroAssembler* masm) {
97080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Just jump directly to runtime if native RegExp is not selected at compile
97180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // time or if regexp entry in generated code is turned off runtime switch or
97280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // at compilation.
97380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef V8_INTERPRETED_REGEXP
974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1);
97580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#else  // V8_INTERPRETED_REGEXP
97680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
97780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Stack frame on entry.
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[0]  : return address
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[8]  : last_match_info (expected JSArray)
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[16] : previous index
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[24] : subject string
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[32] : JSRegExp object
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum RegExpExecStubArgumentIndices {
985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JS_REG_EXP_OBJECT_ARGUMENT_INDEX,
986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SUBJECT_STRING_ARGUMENT_INDEX,
987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PREVIOUS_INDEX_ARGUMENT_INDEX,
988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    LAST_MATCH_INFO_ARGUMENT_INDEX,
989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    REG_EXP_EXEC_ARGUMENT_COUNT
990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, REG_EXP_EXEC_ARGUMENT_COUNT,
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ARGUMENTS_DONT_CONTAIN_RECEIVER);
99480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label runtime;
99580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Ensure that a RegExp stack is allocated.
99680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ExternalReference address_of_regexp_stack_memory_address =
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_regexp_stack_memory_address(isolate());
99880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ExternalReference address_of_regexp_stack_memory_size =
999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::address_of_regexp_stack_memory_size(isolate());
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Load(kScratchRegister, address_of_regexp_stack_memory_size);
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(kScratchRegister, kScratchRegister);
100280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &runtime);
100380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
100480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the first argument is a JSRegExp object.
1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
100680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfSmi(rax, &runtime);
100780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister);
100880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_equal, &runtime);
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
101080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the RegExp has been compiled (data contains a fixed array).
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rax, JSRegExp::kDataOffset));
101280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
101344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Condition is_smi = masm->CheckSmi(rax);
101480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Check(NegateCondition(is_smi),
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        kUnexpectedTypeForRegExpDataFixedArrayExpected);
101644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ CmpObjectType(rax, FIXED_ARRAY_TYPE, kScratchRegister);
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(equal, kUnexpectedTypeForRegExpDataFixedArrayExpected);
101880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
101980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
102044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // rax: RegExp data (FixedArray)
102180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ SmiToInteger32(rbx, FieldOperand(rax, JSRegExp::kDataTagOffset));
102380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP));
102480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_equal, &runtime);
102580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // rax: RegExp data (FixedArray)
102780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the number of captures fit in the static offsets vector buffer.
102880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ SmiToInteger32(rdx,
102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                    FieldOperand(rax, JSRegExp::kIrregexpCaptureCountOffset));
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check (number_of_captures + 1) * 2 <= offsets vector size
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Or              number_of_captures <= offsets vector size / 2 - 1
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpl(rdx, Immediate(Isolate::kJSRegexpStaticOffsetsVectorSize / 2 - 1));
103480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(above, &runtime);
103580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
103669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Reset offset for possibly sliced string.
103769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Set(r14, 0);
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(rdi, &runtime);
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r15, rdi);  // Make a copy of the original subject string.
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
104280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rax: RegExp data (FixedArray)
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi: subject string
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r15: subject string
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handle subject string according to its encoding and representation:
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (1) Sequential two byte?  If yes, go to (9).
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (2) Sequential one byte?  If yes, go to (6).
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (3) Anything but sequential or cons?  If yes, go to (7).
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (4) Cons string.  If the string is flat, replace subject with first string.
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     Otherwise bailout.
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (5a) Is subject sequential two byte?  If yes, go to (9).
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (5b) Is subject external?  If yes, go to (8).
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (6) One byte sequential.  Load regexp code for one byte.
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (E) Carry on.
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  /// [...]
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Deferred code at the end of the stub:
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (7) Not a long external string?  If yes, go to (10).
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (8) External string.  Make it, offset-wise, look like a sequential string.
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (8a) Is the external string one byte?  If yes, go to (6).
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (9) Two byte sequential.  Load regexp code for one byte. Go to (E).
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (10) Short external string or not a string?  If yes, bail out to runtime.
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (11) Sliced string.  Replace subject with parent. Go to (5a).
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label seq_one_byte_string /* 6 */, seq_two_byte_string /* 9 */,
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        external_string /* 8 */, check_underlying /* 5a */,
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        not_seq_nor_cons /* 7 */, check_code /* E */,
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        not_long_external /* 10 */;
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (1) Sequential two byte?  If yes, go to (9).
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ andb(rbx, Immediate(kIsNotStringMask |
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         kStringRepresentationMask |
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         kStringEncodingMask |
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         kShortExternalStringMask));
107680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &seq_two_byte_string);  // Go to (9).
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (2) Sequential one byte?  If yes, go to (6).
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Any other sequential string must be one byte.
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ andb(rbx, Immediate(kIsNotStringMask |
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         kStringRepresentationMask |
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         kShortExternalStringMask));
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &seq_one_byte_string, Label::kNear);  // Go to (6).
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (3) Anything but sequential or cons?  If yes, go to (7).
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We check whether the subject string is a cons, since sequential strings
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // have already been covered.
108969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kConsStringTag < kExternalStringTag);
109069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rbx, Immediate(kExternalStringTag));
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(greater_equal, &not_seq_nor_cons);  // Go to (7).
109569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (4) Cons string.  Check that it's flat.
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Replace subject with first string and reload instance type.
109844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset),
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Heap::kempty_stringRootIndex);
110080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_equal, &runtime);
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rdi, ConsString::kFirstOffset));
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&check_underlying);
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
110580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (5a) Is subject sequential two byte?  If yes, go to (9).
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testb(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask));
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &seq_two_byte_string);  // Go to (9).
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (5b) Is subject external?  If yes, go to (8).
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testb(rbx, Immediate(kStringRepresentationMask));
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The underlying external string is never a short external string.
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &external_string);  // Go to (8)
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (6) One byte sequential.  Load regexp code for one byte.
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&seq_one_byte_string);
1119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // rax: RegExp data (FixedArray)
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r11, FieldOperand(rax, JSRegExp::kDataOneByteCodeOffset));
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(rcx, 1);  // Type is one byte.
112280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (E) Carry on.  String handling is done.
112480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&check_code);
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r11: irregexp code
112680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the irregexp code has been generated for the actual string
112780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // encoding. If it has, the field contains a code object otherwise it contains
1128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // smi (code flushing support)
1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfSmi(r11, &runtime);
113080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi: sequential subject string (or look-alike, external string)
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r15: original subject string
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rcx: encoding of subject string (1 if one_byte, 0 if two_byte);
113480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // r11: code
113580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load used arguments before starting to push arguments for call to native
113680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // RegExp code to avoid handling changing stack height.
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We have to use r15 instead of rdi to load the length because rdi might
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // have been only made to look like a sequential string when it actually
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is an external string.
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, args.GetArgumentOperand(PREVIOUS_INDEX_ARGUMENT_INDEX));
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotSmi(rbx, &runtime);
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiCompare(rbx, FieldOperand(r15, String::kLengthOffset));
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(above_equal, &runtime);
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger64(rbx, rbx);
114580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // rdi: subject string
114780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rbx: previous index
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rcx: encoding of subject string (1 if one_byte 0 if two_byte);
114980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // r11: code
115080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // All checks done. Now push arguments for native regexp code.
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Counters* counters = isolate()->counters();
115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->regexp_entry_native(), 1);
115380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
115444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Isolates: note we add an additional parameter here (isolate pointer).
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kRegExpExecuteArguments = 9;
115680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  int argument_slots_on_stack =
115780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ EnterApiExitFrame(argument_slots_on_stack);
115980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Argument 9: Pass current isolate address.
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadAddress(kScratchRegister,
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 ExternalReference::isolate_address(isolate()));
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kRegisterSize),
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          kScratchRegister);
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Argument 8: Indicate that this is a direct call from JavaScript.
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kRegisterSize),
116880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Immediate(1));
116980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Argument 7: Start (high end) of backtracking stack memory area.
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(kScratchRegister, address_of_regexp_stack_memory_address);
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r9, Operand(kScratchRegister, 0));
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(kScratchRegister, address_of_regexp_stack_memory_size);
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r9, Operand(kScratchRegister, 0));
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kRegisterSize), r9);
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Argument 6: Set the number of capture registers to zero to force global
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // regexps to behave as non-global.  This does not affect non-global regexps.
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Argument 6 is passed in r9 on Linux and on the stack on Windows.
118080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kRegisterSize),
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Immediate(0));
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(r9, 0);
118580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
118680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
118780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Argument 5: static offsets vector buffer.
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadAddress(
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      r8, ExternalReference::address_of_static_offsets_vector(isolate()));
119080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Argument 5 passed in r8 on Linux and on the stack on Windows.
119180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kRegisterSize), r8);
119380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
119480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // rdi: subject string
119680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rbx: previous index
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rcx: encoding of subject string (1 if one_byte 0 if two_byte);
119880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // r11: code
119969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // r14: slice offset
120069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // r15: original subject string
120169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
120269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Argument 2: Previous index.
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(arg_reg_2, rbx);
120480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
120580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Argument 4: End of string data
120680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Argument 3: Start of string data
120769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Label setup_two_byte, setup_rest, got_length, length_not_from_slice;
120869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Prepare start and end index of the input.
120969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Load the length from the original sliced string if that is the case.
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rbx, r14);
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(arg_reg_3, FieldOperand(r15, String::kLengthOffset));
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r14, arg_reg_3);  // Using arg3 as scratch.
121369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
121469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // rbx: start index of the input
121569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // r14: end index of the input
121669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // r15: original subject string
1217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ testb(rcx, rcx);  // Last use of rcx as encoding of subject string.
1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(zero, &setup_two_byte, Label::kNear);
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(arg_reg_4,
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(rdi, r14, times_1, SeqOneByteString::kHeaderSize));
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(arg_reg_3,
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(rdi, rbx, times_1, SeqOneByteString::kHeaderSize));
1223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(&setup_rest, Label::kNear);
122480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&setup_two_byte);
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(arg_reg_4,
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize));
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(arg_reg_3,
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize));
122980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&setup_rest);
123080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
123169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Argument 1: Original subject string.
123269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The original subject is in the previous stack frame. Therefore we have to
123369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // use rbp, which points exactly to one pointer size below the previous rsp.
123469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // (Because creating a new stack frame pushes the previous rbp onto the stack
123569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // and thereby moves up rsp by one kPointerSize.)
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(arg_reg_1, r15);
123780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
123880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Locate the code entry and call it.
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
1240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ call(r11);
124180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LeaveApiExitFrame(true);
124380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
124480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check the result.
1245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label success;
1246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Label exception;
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpl(rax, Immediate(1));
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We expect exactly one result since we force the called regexp to behave
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // as non-global.
1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &success, Label::kNear);
125180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION));
1252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ j(equal, &exception);
1253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If none of the above, it can only be retry.
1255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Handle that in the runtime system.
125680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_equal, &runtime);
1257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // For failure return null.
1259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ LoadRoot(rax, Heap::kNullValueRootIndex);
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
126180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
126280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load RegExp data.
126380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&success);
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, args.GetArgumentOperand(JS_REG_EXP_OBJECT_ARGUMENT_INDEX));
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rax, JSRegExp::kDataOffset));
126680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ SmiToInteger32(rax,
126780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
126880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Calculate number of capture registers (number_of_captures + 1) * 2.
126980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ leal(rdx, Operand(rax, rax, times_1, 2));
127080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
127180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rdx: Number of capture registers
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the fourth object is a JSArray object.
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r15, args.GetArgumentOperand(LAST_MATCH_INFO_ARGUMENT_INDEX));
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(r15, &runtime);
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpObjectType(r15, JS_ARRAY_TYPE, kScratchRegister);
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &runtime);
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the JSArray is in fast case.
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(r15, JSArray::kElementsOffset));
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, FieldOperand(rbx, HeapObject::kMapOffset));
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareRoot(rax, Heap::kFixedArrayMapRootIndex);
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &runtime);
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that the last match info has space for the capture registers and the
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // additional information. Ensure no overflow in add.
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset));
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subl(rax, Immediate(RegExpImpl::kLastMatchOverhead));
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpl(rdx, rax);
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(greater, &runtime);
128980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rbx: last_match_info backing store (FixedArray)
129180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rdx: number of capture registers
129280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Store the capture count.
129380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Integer32ToSmi(kScratchRegister, rdx);
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset),
129580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          kScratchRegister);
129680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Store last subject and last input.
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, args.GetArgumentOperand(SUBJECT_STRING_ARGUMENT_INDEX));
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax);
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, rax);
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(rbx,
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      RegExpImpl::kLastSubjectOffset,
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      rax,
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      rdi,
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs);
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, rcx);
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax);
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWriteField(rbx,
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      RegExpImpl::kLastInputOffset,
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      rax,
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      rdi,
13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs);
131280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
131380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Get the static offsets vector filled by the native regexp code.
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadAddress(
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rcx, ExternalReference::address_of_static_offsets_vector(isolate()));
131680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
131780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rbx: last_match_info backing store (FixedArray)
131880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx: offsets vector
131980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rdx: number of capture registers
1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label next_capture, done;
132180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Capture register counter starts from number of capture registers and
132280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // counts down until wraping after zero.
132380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&next_capture);
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, Immediate(1));
1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(negative, &done, Label::kNear);
132680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Read the value from the static offsets vector buffer and make it a smi.
132780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movl(rdi, Operand(rcx, rdx, times_int_size, 0));
13280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Integer32ToSmi(rdi, rdi);
132980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Store the smi value in the last match info.
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx,
133180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                       rdx,
133280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                       times_pointer_size,
133380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                       RegExpImpl::kFirstCaptureOffset),
133480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          rdi);
133580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&next_capture);
133680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
133780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
133880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Return last match info.
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, r15);
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(REG_EXP_EXEC_ARGUMENT_COUNT * kPointerSize);
134180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&exception);
1343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Result must now be exception. If there is no pending exception already a
1344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // stack overflow (on the backtrack stack) was detected in RegExp code but
1345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // haven't created the exception yet. Handle that in the runtime system.
1346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ExternalReference pending_exception_address(
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Isolate::kPendingExceptionAddress, isolate());
134944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand pending_exception_operand =
135044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      masm->ExternalOperand(pending_exception_address, rbx);
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, pending_exception_operand);
1352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rax, rdx);
1354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ j(equal, &runtime);
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(pending_exception_operand, rdx);
1356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label termination_exception;
1359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &termination_exception, Label::kNear);
1360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ Throw(rax);
1361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ bind(&termination_exception);
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ThrowUncatchable(rax);
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do the runtime call to execute the regexp.
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&runtime);
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1);
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Deferred code for string handling.
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (7) Not a long external string?  If yes, go to (10).
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_seq_nor_cons);
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compare flags are still set from (3).
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(greater, &not_long_external, Label::kNear);  // Go to (10).
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (8) External string.  Short external strings have been ruled out.
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&external_string);
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assert that we do not have a cons or slice (indirect strings) here.
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Sequential strings have already been ruled out.
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ testb(rbx, Immediate(kIsIndirectStringMask));
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(zero, kExternalStringExpectedButNotFound);
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Move the pointer so that offset-wise, it looks like a sequential string.
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kTwoByteStringTag == 0);
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (8a) Is the external string one byte?  If yes, go to (6).
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testb(rbx, Immediate(kStringEncodingMask));
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &seq_one_byte_string);  // Goto (6).
1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi: subject string (flat two-byte)
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rax: RegExp data (FixedArray)
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (9) Two byte sequential.  Load regexp code for one byte.  Go to (E).
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&seq_two_byte_string);
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(rcx, 0);  // Type is two byte.
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&check_code);  // Go to (E).
1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (10) Not a string or a short external string?  If yes, bail out to runtime.
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_long_external);
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Catch non-string subject or short external string.
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testb(rbx, Immediate(kIsNotStringMask | kShortExternalStringMask));
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &runtime);
140880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (11) Sliced string.  Replace subject with parent. Go to (5a).
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load offset into r14 and replace subject string with parent.
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset));
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rdi, SlicedString::kParentOffset));
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&check_underlying);
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_INTERPRETED_REGEXP
141580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
141680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
141780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int NegativeComparisonResult(Condition cc) {
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc != equal);
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((cc == less) || (cc == less_equal)
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      || (cc == greater) || (cc == greater_equal));
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (cc == greater || cc == greater_equal) ? LESS : GREATER;
142380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
142480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
142580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CheckInputType(MacroAssembler* masm, Register input,
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           CompareICState::State expected, Label* fail) {
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label ok;
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expected == CompareICState::SMI) {
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfNotSmi(input, fail);
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (expected == CompareICState::NUMBER) {
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(input, &ok);
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareMap(input, masm->isolate()->factory()->heap_number_map());
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, fail);
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We could be strict about internalized/non-internalized here, but as long as
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hydrogen doesn't care, the stub doesn't have to care either.
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&ok);
143980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
144080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
144180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void BranchIfNotInternalizedString(MacroAssembler* masm,
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Label* label,
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Register object,
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Register scratch) {
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(object, label);
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, FieldOperand(object, HeapObject::kMapOffset));
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(scratch,
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             FieldOperand(scratch, Map::kInstanceTypeOffset));
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, label);
145380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
145480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
145580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateGeneric(MacroAssembler* masm) {
145780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label check_unequal_objects, done;
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cc = GetCondition();
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = isolate()->factory();
14600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label miss;
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInputType(masm, rdx, left(), &miss);
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CheckInputType(masm, rax, right(), &miss);
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compare two smis.
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label non_smi, smi_done;
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotBothSmi(rax, rdx, &non_smi);
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdx, rax);
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(no_overflow, &smi_done);
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ notp(rdx);  // Correct sign in case of overflow. rdx cannot be 0 here.
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&smi_done);
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, rdx);
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(0);
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&non_smi);
14750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
147680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The compare stub returns a positive, negative, or zero 64-bit integer
147780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // value in rax, corresponding to result of comparing the two inputs.
147880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // NOTICE! This code is only reached after a smi-fast-case check, so
147980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // it is certain that at least one operand isn't a smi.
148080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
148180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Two identical objects are equal unless they are both NaN or undefined.
148280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  {
1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label not_identical;
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(rax, rdx);
1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &not_identical, Label::kNear);
148680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (cc != equal) {
148880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Check for undefined.  undefined OP undefined is false even though
148980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // undefined == undefined.
1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label check_for_nan;
149180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ j(not_equal, &check_for_nan, Label::kNear);
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Set(rax, NegativeComparisonResult(cc));
149480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ ret(0);
149580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&check_for_nan);
149680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
149780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
149980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // so we do the second best thing - test it ourselves.
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label heap_number;
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If it's not a heap number, then return equal for (in)equality operator.
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           factory->heap_number_map());
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, &heap_number, Label::kNear);
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (cc != equal) {
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Call runtime on identical objects.  Otherwise return equal.
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(above_equal, &not_identical, Label::kNear);
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Set(rax, EQUAL);
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ret(0);
151280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&heap_number);
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It is a heap number, so return  equal if it's not NaN.
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For NaN, return 1 for every condition except greater and
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // greater-equal.  Return -1 for them, so the comparison yields
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // false for all conditions except not-equal.
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Set(rax, EQUAL);
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ucomisd(xmm0, xmm0);
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ setcc(parity_even, rax);
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // rax is 0 for equal non-NaN heapnumbers, 1 for NaNs.
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (cc == greater_equal || cc == greater) {
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ negp(rax);
152580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ret(0);
152780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
152880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&not_identical);
152980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
153080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == equal) {  // Both strict and non-strict.
153280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Label slow;  // Fallthrough label.
153380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
153480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // If we're doing a strict equality comparison, we don't have to do
153580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // type conversion, so we generate code to do fast comparison for objects
153680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // and oddballs. Non-smi numbers and strings still go through the usual
153780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // slow-case code.
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (strict()) {
153980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // If either is a Smi (we know that not both are), then they can only
154080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // be equal if the other is a HeapNumber. If so, use the slow case.
154180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      {
154280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        Label not_smis;
154380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ SelectNonSmi(rbx, rax, rdx, &not_smis);
154480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
154580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        // Check if the non-smi operand is a heap number.
154680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
1547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               factory->heap_number_map());
154880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        // If heap number, handle it in the slow case.
154980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ j(equal, &slow);
155080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        // Return non-equal.  ebx (the lower half of rbx) is not zero.
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ movp(rax, rbx);
155280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ ret(0);
155380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
155480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        __ bind(&not_smis);
155580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
155680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
155780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // If either operand is a JSObject or an oddball value, then they are not
155880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // equal since their pointers are different
155980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // There is no test for undetectability in strict equality.
156080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
156180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // If the first object is a JS object, we have done pointer comparison.
15623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
1563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      Label first_non_object;
15643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      __ j(below, &first_non_object, Label::kNear);
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Return non-zero (rax (not rax) is not zero)
156780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Label return_not_equal;
156880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      STATIC_ASSERT(kHeapObjectTag != 0);
156980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&return_not_equal);
157080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ ret(0);
157180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
157280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ bind(&first_non_object);
157380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Check for oddballs: true, false, null, undefined.
157480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ CmpInstanceType(rcx, ODDBALL_TYPE);
157580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(equal, &return_not_equal);
157680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
15773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx);
157880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(above_equal, &return_not_equal);
157980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
158080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Check for oddballs: true, false, null, undefined.
158180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ CmpInstanceType(rcx, ODDBALL_TYPE);
158280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      __ j(equal, &return_not_equal);
158380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
158480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Fall through to the general case.
158580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
158680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&slow);
158780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
158880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
158980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Generate the number comparison code.
1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label non_number_comparison;
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label unordered;
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison);
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ xorl(rax, rax);
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ xorl(rcx, rcx);
1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ucomisd(xmm0, xmm1);
159680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Don't base result on EFLAGS when a NaN is involved.
1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(parity_even, &unordered, Label::kNear);
1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return a result of -1, 0, or 1, based on EFLAGS.
1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ setcc(above, rax);
1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ setcc(below, rcx);
1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rax, rcx);
1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(0);
160480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If one of the numbers was NaN, then the result is always false.
1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The cc is never not-equal.
1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&unordered);
1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(cc != not_equal);
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == less || cc == less_equal) {
1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Set(rax, 1);
1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Set(rax, -1);
161380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(0);
161580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The number comparison code did not provide a valid result.
1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&non_number_comparison);
161880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fast negative check for internalized-to-internalized equality.
1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label check_for_strings;
1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == equal) {
1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BranchIfNotInternalizedString(
1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm, &check_for_strings, rax, kScratchRegister);
1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BranchIfNotInternalizedString(
1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm, &check_for_strings, rdx, kScratchRegister);
1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We've already checked for object identity, so if both operands are
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // internalized strings they aren't equal. Register rax (not rax) already
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // holds a non-zero value, which indicates not equal, so just return.
163080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ret(0);
163180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
163280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
163380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&check_for_strings);
163480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotBothSequentialOneByteStrings(rdx, rax, rcx, rbx,
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           &check_unequal_objects);
163780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline comparison of one-byte strings.
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == equal) {
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StringHelper::GenerateFlatOneByteStringEquals(masm, rdx, rax, rcx, rbx);
1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else {
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StringHelper::GenerateCompareFlatOneByteStrings(masm, rdx, rax, rcx, rbx,
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                    rdi, r8);
1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
164580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
164680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef DEBUG
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Abort(kUnexpectedFallThroughFromStringComparison);
164880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
164980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
165080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&check_unequal_objects);
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == equal && !strict()) {
165280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Not strict equality.  Objects are unequal if
165380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // they are both JSObjects and not undetectable,
165480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // and their pointers are different.
1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label not_both_objects, return_unequal;
165680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // At most one is a smi, so we can test for smi by adding the two.
165780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // A smi plus a heap object has the low bit set, a heap object plus
165880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // a heap object has the low bit clear.
165980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    STATIC_ASSERT(kSmiTag == 0);
166080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    STATIC_ASSERT(kSmiTagMask == 1);
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(rcx, Operand(rax, rdx, times_1, 0));
166280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(rcx, Immediate(kSmiTagMask));
1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_zero, &not_both_objects, Label::kNear);
16643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(below, &not_both_objects, Label::kNear);
16663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx);
1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(below, &not_both_objects, Label::kNear);
166880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
166980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(zero, &return_unequal, Label::kNear);
167180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
167280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen             Immediate(1 << Map::kIsUndetectable));
1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(zero, &return_unequal, Label::kNear);
167480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // The objects are both undetectable, so they both compare as the value
167580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // undefined, and are equal.
167680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ Set(rax, EQUAL);
167780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&return_unequal);
16781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Return non-equal by returning the non-zero object pointer in rax,
167980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // or return equal if we fell through to here.
168080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ ret(0);
168180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&not_both_objects);
168280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
168380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
168480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Push arguments below the return address to prepare jump to builtin.
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(rcx);
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
168880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
168980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Figure out which native to call and setup the arguments.
169080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Builtins::JavaScript builtin;
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (cc == equal) {
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
169380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
169480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    builtin = Builtins::COMPARE;
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Smi::FromInt(NegativeComparisonResult(cc)));
169680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
169780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(rcx);
169980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
170080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
170180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // tagged as a small integer.
170280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ InvokeBuiltin(builtin, JUMP_FUNCTION);
170380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&miss);
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateMiss(masm);
17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateRecordCallTarget(MacroAssembler* masm) {
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Cache the called function in a feedback vector slot.  Cache states
17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // are uninitialized, monomorphic (indicated by a JSFunction), and
17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // megamorphic.
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rax : number of arguments to the construct function
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx : Feedback vector
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdx : slot in feedback vector (Smi)
17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdi : the function to call
17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Isolate* isolate = masm->isolate();
1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label initialize, done, miss, megamorphic, not_array_function,
1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      done_no_smi_convert;
17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Load the cache state into rcx.
1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rdx, rdx);
1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size,
1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            FixedArray::kHeaderSize));
17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A monomorphic cache hit or an already megamorphic state: invoke the
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // function without changing the state.
1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rcx, rdi);
1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &done);
1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate));
1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &done);
1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_pretenuring_call_new) {
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we came here, we need to see if we are the array function.
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we didn't have a matching function, and we didn't find the megamorph
1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // sentinel, then we have in the slot either some other function or an
1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // AllocationSite. Do a map check on the object in rcx.
1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Map> allocation_site_map =
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm->isolate()->factory()->allocation_site_map();
1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cmp(FieldOperand(rcx, 0), allocation_site_map);
1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &miss);
1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make sure the function is the Array() function
1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(rdi, rcx);
1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &megamorphic);
1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done);
1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&miss);
17513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
17533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // megamorphic.
1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(rcx, TypeFeedbackVector::UninitializedSentinel(isolate));
1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &initialize);
17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // MegamorphicSentinel is an immortal immovable object (undefined) so no
17573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // write-barrier is needed.
1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&megamorphic);
1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize),
1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          TypeFeedbackVector::MegamorphicSentinel(isolate));
1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // An uninitialized cache is patched with the function or sentinel to
1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // indicate the ElementsKind if function is the Array constructor.
17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&initialize);
17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_pretenuring_call_new) {
1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Make sure the function is the Array() function
1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(rdi, rcx);
1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &not_array_function);
17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Arguments register must be smi-tagged to call out.
1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Integer32ToSmi(rax, rax);
1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rax);
1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rdi);
1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Integer32ToSmi(rdx, rdx);
1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rdx);
1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(rbx);
1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CreateAllocationSiteStub create_stub(isolate);
1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallStub(&create_stub);
1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rbx);
1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rdx);
1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rdi);
1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rax);
1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ SmiToInteger32(rax, rax);
1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done_no_smi_convert);
1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&not_array_function);
179680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
179780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize),
1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          rdi);
180080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We won't need rdx or rbx anymore, just save rdi
1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdi);
1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rbx);
1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteArray(rbx, rdi, rdx, kDontSaveFPRegs,
1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdx);
1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rbx);
1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rdi);
1810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Integer32ToSmi(rdx, rdx);
181380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done_no_smi_convert);
1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) {
1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do not transform the receiver for strict mode functions.
1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testb(FieldOperand(rcx, SharedFunctionInfo::kStrictModeByteOffset),
1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, cont);
1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Do not transform the receiver for natives.
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // SharedFunctionInfo is already loaded into rcx.
1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset),
1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, cont);
1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitSlowCase(Isolate* isolate,
1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         MacroAssembler* masm,
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         StackArgumentsAccessor* args,
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         int argc,
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* non_function) {
1838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Check for function proxy.
1839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, non_function);
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(rcx);
1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdi);  // put proxy as additional argument under return address
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(rcx);
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(rax, argc + 1);
1845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ Set(rbx, 0);
1846589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY);
1847589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  {
1848589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Handle<Code> adaptor =
1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
1850589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ jmp(adaptor, RelocInfo::CODE_TARGET);
1851589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
1852589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // of the original receiver from the call site).
1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(non_function);
1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args->GetReceiverOperand(), rdi);
1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(rax, argc);
1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(rbx, 0);
1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> adaptor =
1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate->builtins()->ArgumentsAdaptorTrampoline();
1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Jump(adaptor, RelocInfo::CODE_TARGET);
1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitWrapCase(MacroAssembler* masm,
1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         StackArgumentsAccessor* args,
1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         Label* cont) {
1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Wrap the receiver and patch it back onto the stack.
1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  { FrameScope frame_scope(masm, StackFrame::INTERNAL);
1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rdi);
1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rax);
1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(rdi);
1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(args->GetReceiverOperand(), rax);
1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(cont);
1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CallFunctionNoFeedback(MacroAssembler* masm,
1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   int argc, bool needs_checks,
1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   bool call_as_method) {
1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi : the function to call
1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // wrap_and_call can only be true if we are compiling a monomorphic method.
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = masm->isolate();
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label slow, non_function, wrap, cont;
1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, argc);
1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (needs_checks) {
1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check that the function really is a JavaScript function.
1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(rdi, &non_function);
1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Goto slow case if we do not have a function.
1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &slow);
1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fast-case: Just invoke the function.
1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ParameterCount actual(argc);
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (call_as_method) {
1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (needs_checks) {
1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmitContinueIfStrictOrNative(masm, &cont);
1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the receiver from the stack.
1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, args.GetReceiverOperand());
1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (needs_checks) {
1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ JumpIfSmi(rax, &wrap);
1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(below, &wrap);
1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ jmp(&wrap);
1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&cont);
1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper());
1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (needs_checks) {
1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Slow-case: Non-function called.
1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&slow);
1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitSlowCase(isolate, masm, &args, argc, &non_function);
1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (call_as_method) {
1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&wrap);
1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitWrapCase(masm, &args, &cont);
1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallFunctionStub::Generate(MacroAssembler* masm) {
1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod());
194080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
194180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
194280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
19433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallConstructStub::Generate(MacroAssembler* masm) {
19443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rax : number of arguments
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx : feedback vector
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdx : (only if rbx is not the megamorphic symbol) slot in feedback
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //       vector (Smi)
19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdi : constructor function
19493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow, non_function_call;
19503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that function is not a smi.
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rdi, &non_function_call);
19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check that function is a JSFunction.
19543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &slow);
19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (RecordCallTarget()) {
19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenerateRecordCallTarget(masm);
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiToInteger32(rdx, rdx);
1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_pretenuring_call_new) {
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Put the AllocationSite from the feedback vector into ebx.
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // By adding kPointerSize we encode that we know the AllocationSite
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // entry is at the feedback vector slot given by rdx + 1.
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size,
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                FixedArray::kHeaderSize + kPointerSize));
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label feedback_register_initialized;
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Put the AllocationSite from the feedback vector into rbx, or undefined.
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size,
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                FixedArray::kHeaderSize));
1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CompareRoot(FieldOperand(rbx, 0), Heap::kAllocationSiteMapRootIndex);
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(equal, &feedback_register_initialized);
1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&feedback_register_initialized);
1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ AssertUndefinedOrAllocationSite(rbx);
19793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
19803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Jump to the function-specific construct stub.
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register jmp_reg = rcx;
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(jmp_reg, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(jmp_reg, FieldOperand(jmp_reg,
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                SharedFunctionInfo::kConstructStubOffset));
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize));
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(jmp_reg);
19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdi: called object
19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rax: number of arguments
19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rcx: object map
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label do_call;
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&slow);
19943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE);
19953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &non_function_call);
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
19973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&do_call);
19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&non_function_call);
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
20013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&do_call);
20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set expected number of arguments to zero (not changing rax).
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Set(rbx, 0);
2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(),
20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          RelocInfo::CODE_TARGET);
20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
20073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(vector, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(vector, FieldOperand(vector,
2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               SharedFunctionInfo::kFeedbackVectorOffset));
201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallIC_ArrayStub::Generate(MacroAssembler* masm) {
2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi - function
2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdx - slot id (as integer)
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label miss;
2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int argc = arg_count();
2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ParameterCount actual(argc);
2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadTypeFeedbackVector(masm, rbx);
2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rdx, rdx);
2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rdi, rcx);
2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &miss);
2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, Immediate(arg_count()));
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size,
2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            FixedArray::kHeaderSize));
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify that ecx contains an AllocationSite
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = masm->isolate()->factory();
2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         factory->allocation_site_map());
2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &miss);
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, rcx);
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArrayConstructorStub stub(masm->isolate(), arg_count());
2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallStub(&stub);
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&miss);
2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateMiss(masm);
2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The slow case, we need this no matter what to complete a call after a miss.
2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallFunctionNoFeedback(masm,
2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         arg_count(),
2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         true,
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         CallAsMethod());
2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unreachable.
2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ int3();
2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallICStub::Generate(MacroAssembler* masm) {
2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi - function
2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdx - slot id
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = masm->isolate();
2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label extra_checks_or_miss, slow_start;
2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label slow, non_function, wrap, cont;
2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label have_js_function;
2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int argc = arg_count();
2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, argc);
2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ParameterCount actual(argc);
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadTypeFeedbackVector(masm, rbx);
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The checks. First, does rdi match the recorded monomorphic target?
2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rdx, rdx);
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rdi, FieldOperand(rbx, rdx, times_pointer_size,
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            FixedArray::kHeaderSize));
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &extra_checks_or_miss);
2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&have_js_function);
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CallAsMethod()) {
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitContinueIfStrictOrNative(masm, &cont);
2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load the receiver from the stack.
2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, args.GetReceiverOperand());
2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(rax, &wrap);
2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(below, &wrap);
2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&cont);
2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper());
2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&slow);
2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitSlowCase(isolate, masm, &args, argc, &non_function);
2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CallAsMethod()) {
2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&wrap);
2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmitWrapCase(masm, &args, &cont);
2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&extra_checks_or_miss);
2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label miss;
2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size,
2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            FixedArray::kHeaderSize));
2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate));
2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &slow_start);
2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cmp(rcx, TypeFeedbackVector::UninitializedSentinel(isolate));
2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &miss);
2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_trace_ic) {
2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We are going megamorphic. If the feedback is a JSFunction, it is fine
2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to handle it here. More complex cases are dealt with in the runtime.
2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ AssertNotSmi(rcx);
2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(rcx, JS_FUNCTION_TYPE, rcx);
2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &miss);
2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize),
2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            TypeFeedbackVector::MegamorphicSentinel(isolate));
2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&slow_start);
2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We are here because tracing is on or we are going monomorphic.
2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&miss);
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateMiss(masm);
2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the slow case
2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&slow_start);
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that function is not a smi.
2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(rdi, &non_function);
2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that function is a JSFunction.
2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &slow);
2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&have_js_function);
2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unreachable
2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ int3();
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallICStub::GenerateMiss(MacroAssembler* masm) {
2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the receiver of the function from the stack; 1 ~ return address.
2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, Operand(rsp, (arg_count() + 1) * kPointerSize));
2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Push the receiver and the function and feedback info.
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rcx);
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rdi);
2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rbx);
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Integer32ToSmi(rdx, rdx);
2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rdx);
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Call the entry.
2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               : IC::kCallIC_Customization_Miss;
2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference miss = ExternalReference(IC_Utility(id),
2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               masm->isolate());
2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallExternalReference(miss, 4);
2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move result to edi and exit the internal frame.
2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdi, rax);
2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CEntryStub::NeedsImmovableCode() {
2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return false;
21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub::GenerateAheadOfTime(isolate);
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It is important that the store buffer overflow stubs are generated first.
2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BinaryOpICStub::GenerateAheadOfTime(isolate);
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CodeStub::GenerateFPStubs(Isolate* isolate) {
21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
21893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(isolate, 1, kDontSaveFPRegs);
2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  stub.GetCode();
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub save_doubles(isolate, 1, kSaveFPRegs);
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  save_doubles.GetCode();
2195592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
2196592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2197592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CEntryStub::Generate(MacroAssembler* masm) {
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rax: number of arguments including receiver
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx: pointer to C function  (C callee-saved)
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbp: frame pointer of calling JS frame (restored after C call)
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp: stack pointer  (restored after C call)
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsi: current context (restored)
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileEntryHookStub::MaybeCallEntryHook(masm);
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Enter the exit frame that transitions from JavaScript to C++.
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_stack_space = (result_size() < 2 ? 2 : 4);
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else   // _WIN64
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int arg_stack_space = 0;
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // _WIN64
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ EnterExitFrame(arg_stack_space, save_doubles());
2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx: pointer to builtin function  (C callee-saved).
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbp: frame pointer of exit frame  (restored after C call).
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp: stack pointer (restored after C call).
221880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // r14: number of arguments including receiver (C callee-saved).
2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r15: argv pointer (C callee-saved).
222080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
222180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Simple results returned in rax (both AMD64 and Win64 calling conventions).
222280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Complex results must be written to address passed as first argument.
222380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // AMD64 calling convention: a struct of two pointers in rax+rdx
222480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
222580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check stack alignment.
222680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (FLAG_debug_code) {
222780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CheckStackAlignment();
222880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
222980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
223080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Call C function.
223180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64
2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9.
2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Pass argv and argc as two parameters. The arguments object will
2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // be created by stubs declared by DECLARE_RUNTIME_FUNCTION().
2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result_size() < 2) {
223680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Pass a pointer to the Arguments object as the first argument.
223780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Return result in single register (rax).
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, r14);  // argc.
2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, r15);  // argv.
2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(r8, ExternalReference::isolate_address(isolate()));
224180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(2, result_size());
224380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Pass a pointer to the result location as the first argument.
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(rcx, StackSpaceOperand(2));
224580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Pass a pointer to the Arguments object as the second argument.
2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rdx, r14);  // argc.
2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(r8, r15);   // argv.
2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(r9, ExternalReference::isolate_address(isolate()));
224980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
225080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
225180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#else  // _WIN64
225280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, r14);  // argc.
2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rsi, r15);  // argv.
2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rdx, ExternalReference::isolate_address(isolate()));
2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // _WIN64
225780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ call(rbx);
225880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Result is in rax - do not destroy this register!
225980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
226080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64
226180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If return value is on the stack, pop it to registers.
2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (result_size() > 1) {
2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(2, result_size());
226480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Read result values stored on stack. Result is stored
226580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // above the four argument mirror slots and the two
226680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Arguments object slots.
2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(rax, Operand(rsp, 6 * kRegisterSize));
2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(rdx, Operand(rsp, 7 * kRegisterSize));
226980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // _WIN64
227180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Runtime functions should not return 'the hole'.  Allowing it to escape may
2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // lead to crashes in the IC code later.
2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label okay;
2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_equal, &okay, Label::kNear);
2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ int3();
2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&okay);
2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check result for exception sentinel.
2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label exception_returned;
2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareRoot(rax, Heap::kExceptionRootIndex);
2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &exception_returned);
228680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference pending_exception_address(
2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Isolate::kPendingExceptionAddress, isolate());
2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that there is no pending exception, otherwise we
2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // should have returned the exception sentinel.
2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label okay;
2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(r14, Heap::kTheHoleValueRootIndex);
2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Operand pending_exception_operand =
2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm->ExternalOperand(pending_exception_address);
2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(r14, pending_exception_operand);
2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, &okay, Label::kNear);
2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ int3();
2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&okay);
2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
230280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Exit the JavaScript to C++ exit frame.
2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LeaveExitFrame(save_doubles());
2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(0);
230680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Handling of exception.
2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&exception_returned);
230980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Retrieve the pending exception.
231144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Operand pending_exception_operand =
231244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      masm->ExternalOperand(pending_exception_address);
2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, pending_exception_operand);
2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear the pending exception.
231644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(pending_exception_operand, rdx);
231880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
231980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Special handling of termination exceptions which are uncatchable
232080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // by javascript code.
2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label throw_termination_exception;
232280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex);
2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &throw_termination_exception);
232480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
232580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Handle normal exception.
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Throw(rax);
232780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
232880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&throw_termination_exception);
23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ThrowUncatchable(rax);
233080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
233180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
233280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid JSEntryStub::Generate(MacroAssembler* masm) {
23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label invoke, handler_entry, exit;
233580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label not_outermost_js, not_outermost_js_2;
2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileEntryHookStub::MaybeCallEntryHook(masm);
2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {  // NOLINT. Scope block confuses linter.
234044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up frame.
2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(rbp);
2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rbp, rsp);
234444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
234544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Push the stack frame type marker twice.
2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int marker = type();
234744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Scratch register is neither callee-save, nor an argument register on any
234844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // platform. It's free to use at this point.
234944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Cannot use smi-register for loading yet.
2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Move(kScratchRegister, Smi::FromInt(marker), Assembler::RelocInfoNone());
2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(kScratchRegister);  // context slot
2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(kScratchRegister);  // function slot
2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save callee-saved registers (X64/X32/Win64 calling conventions).
2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(r12);
2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(r13);
2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(r14);
2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(r15);
2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64
2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(rdi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(rsi);  // Only callee save in Win64 ABI, argument in AMD64 ABI.
2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pushq(rbx);
2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
236480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64
2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // On Win64 XMM6-XMM15 are callee-save
2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subp(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize));
2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0), xmm6);
2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1), xmm7);
2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2), xmm8);
2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3), xmm9);
2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4), xmm10);
2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5), xmm11);
2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6), xmm12);
2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7), xmm13);
2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8), xmm14);
2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9), xmm15);
237780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
237844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
237944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Set up the roots and smi constant registers.
238044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Needs to be done before any further smi loads.
238144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ InitializeSmiConstantRegister();
238244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ InitializeRootRegister();
238344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
238480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
238544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Save copies of the top frame descriptor on the stack.
2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, isolate());
238744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  {
238844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(c_entry_fp_operand);
239044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
239180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
239280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If this is the outermost JS call, set js_entry_sp value.
2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate());
239444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Load(rax, js_entry_sp);
2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rax, rax);
239680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_zero, &not_outermost_js);
2397053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, rbp);
239944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Store(js_entry_sp, rax);
2400053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  Label cont;
2401053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ jmp(&cont);
240280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&not_outermost_js);
2403053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
2404053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ bind(&cont);
240580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Jump to a faked try block that does the invoke, with a faked catch
24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // block that sets the pending exception.
24083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&invoke);
24093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&handler_entry);
24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_offset_ = handler_entry.pos();
24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Caught exception: Store result (exception) in the pending exception
24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // field in the JSEnv and return a failure sentinel.
2413589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      isolate());
241544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Store(pending_exception, rax);
2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(rax, Heap::kExceptionRootIndex);
241780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&exit);
241880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Invoke: Link this frame into the handler chain.  There's only one
24203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // handler block in this code object, so its index is 0.
242180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&invoke);
24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PushTryHandler(StackHandler::JS_ENTRY, 0);
242380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
242480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Clear any pending exceptions.
242544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ LoadRoot(rax, Heap::kTheHoleValueRootIndex);
242644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ Store(pending_exception, rax);
242780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
242880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Fake a receiver (NULL).
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Immediate(0));  // receiver
243080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Invoke the function by calling through JS entry trampoline builtin and
24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // pop the faked function when we return. We load the address from an
24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // external reference instead of inlining the call target address directly
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in the code, because the builtin stubs may not have been generated yet
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // at the time this code is generated.
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (type() == StackFrame::ENTRY_CONSTRUCT) {
243744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                      isolate());
243944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Load(rax, construct_entry);
244080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ExternalReference entry(Builtins::kJSEntryTrampoline, isolate());
244244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ Load(rax, entry);
244380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(kScratchRegister, FieldOperand(rax, Code::kHeaderSize));
244580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ call(kScratchRegister);
244680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
244780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Unlink this frame from the handler chain.
2448053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ PopTryHandler();
244980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2450053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ bind(&exit);
2451053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  // Check if the current stack frame is marked as the outermost JS frame.
2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(rbx);
2453053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
245480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_equal, &not_outermost_js_2);
2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(kScratchRegister, js_entry_sp);
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(kScratchRegister, 0), Immediate(0));
245780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&not_outermost_js_2);
245880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
245980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Restore the top frame descriptor from the stack.
2460053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(c_entry_fp_operand);
246244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
246380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
246480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Restore callee-saved registers (X64 conventions).
2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64
2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // On Win64 XMM6-XMM15 are callee-save
2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm6, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0));
2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm7, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1));
2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm8, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2));
2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm9, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3));
2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm10, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4));
2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm11, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5));
2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm12, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6));
2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm13, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7));
2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm14, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8));
2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movdqu(xmm15, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9));
2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize));
2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(rbx);
248180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#ifdef _WIN64
248280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI.
2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(rsi);
2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(rdi);
248580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif
2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(r15);
2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(r14);
2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(r13);
2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(r12);
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rsp, Immediate(2 * kPointerSize));  // remove markers
249180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
249280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Restore frame pointer and return.
2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(rbp);
249480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret(0);
249580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
249680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
249780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
249880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid InstanceofStub::Generate(MacroAssembler* masm) {
249980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Implements "value instanceof function" operator.
250044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Expected input state with no inline cache:
2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   rsp[0]  : return address
2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   rsp[8]  : function pointer
2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   rsp[16] : value
250444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Expected input state with an inline one-element cache:
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   rsp[0]  : return address
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   rsp[8]  : offset from return address to location of inline cache
2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   rsp[16] : function pointer
2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   rsp[24] : value
250980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Returns a bitwise zero to indicate that the value
251080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // is and instance of the function and anything else to
251180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // indicate that the value is not an instance.
251280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fixed register usage throughout the stub.
2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register object = rax;     // Object (lhs).
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register map = rbx;        // Map of the object.
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register function = rdx;   // Function (rhs).
2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register prototype = rdi;  // Prototype of the function.
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = rcx;
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static const int kOffsetToMapCheckValue = 2;
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kOffsetToResultValue = kPointerSize == kInt64Size ? 18 : 14;
252244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The last 4 bytes of the instruction sequence
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   movp(rdi, FieldOperand(rax, HeapObject::kMapOffset))
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   Move(kScratchRegister, Factory::the_hole_value())
252544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // in front of the hole value address.
2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const unsigned int kWordBeforeMapCheckValue =
2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kPointerSize == kInt64Size ? 0xBA49FF78 : 0xBA41FF78;
252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The last 4 bytes of the instruction sequence
252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   __ j(not_equal, &cache_miss);
253044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  //   __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
253144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // before the offset of the hole value in the root array.
2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const unsigned int kWordBeforeResultValue =
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kPointerSize == kInt64Size ? 0x458B4906 : 0x458B4106;
2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0;
253644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(object.code(), InstanceofStub::left().code());
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK_EQ(function.code(), InstanceofStub::right().code());
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the object and function - they are always both needed.
2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Go slow case if the object is a smi.
2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label slow;
2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 2 + extra_argument_offset,
2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ARGUMENTS_DONT_CONTAIN_RECEIVER);
2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasArgsInRegisters()) {
2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(object, args.GetArgumentOperand(0));
2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(function, args.GetArgumentOperand(1));
2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(object, &slow);
255080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
255180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the left hand is a JS object. Leave its map in rax.
2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpObjectType(object, FIRST_SPEC_OBJECT_TYPE, map);
255380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(below, &slow);
2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpInstanceType(map, LAST_SPEC_OBJECT_TYPE);
255580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(above, &slow);
255680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
255744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If there is a call site cache don't look in the global cache, but do the
255844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // real lookup and update the call site cache.
2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) {
256044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Look up the function and the map in the instanceof cache.
2561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label miss;
2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
2563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &miss, Label::kNear);
2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex);
2565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(not_equal, &miss, Label::kNear);
256644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
256844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ bind(&miss);
256944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
257080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the prototype of the function.
2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TryGetFunctionPrototype(function, prototype, &slow, true);
257380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
257480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check that the function prototype is a JS object.
2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(prototype, &slow);
2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CmpObjectType(prototype, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
257780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(below, &slow);
25783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CmpInstanceType(kScratchRegister, LAST_SPEC_OBJECT_TYPE);
257980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(above, &slow);
258080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update the global instanceof or call site inlined cache with the current
2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // map and function. The cached answer will be set when it is known below.
258344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!HasCallSiteInlineCheck()) {
2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The constants for the code patching are based on push instructions
2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // at the call site.
2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!HasArgsInRegisters());
25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Get return address and delta to inlined map check.
2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(kScratchRegister, StackOperandForReturnAddress(0));
2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subp(kScratchRegister, args.GetArgumentOperand(2));
259344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (FLAG_debug_code) {
2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movl(scratch, Immediate(kWordBeforeMapCheckValue));
2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), scratch);
2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck);
259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(kScratchRegister,
25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Operand(kScratchRegister, kOffsetToMapCheckValue));
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(Operand(kScratchRegister, 0), map);
260144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
260280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
260380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Loop through the prototype chain looking for the function prototype.
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, FieldOperand(map, Map::kPrototypeOffset));
2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label loop, is_instance, is_not_instance;
260680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex);
260780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&loop);
2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(scratch, prototype);
2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &is_instance, Label::kNear);
2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(scratch, kScratchRegister);
261180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The code at is_not_instance assumes that kScratchRegister contains a
261280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // non-zero GCable value (the null object in this case).
2613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &is_not_instance, Label::kNear);
2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
261680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&loop);
261780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
261880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&is_instance);
261944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!HasCallSiteInlineCheck()) {
262044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ xorl(rax, rax);
262144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Store bitwise zero in the cache.  This is a Smi in GC terms.
262244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    STATIC_ASSERT(kSmiTag == 0);
262344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (ReturnTrueFalseObject()) {
2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(rax, Heap::kTrueValueRootIndex);
2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
262744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
262844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Store offset of true in the root array at the inline check site.
26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int true_offset = 0x100 +
26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
26313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assert it is a 1-byte signed value.
2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(true_offset >= 0 && true_offset < 0x100);
26333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movl(rax, Immediate(true_offset));
2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(kScratchRegister, StackOperandForReturnAddress(0));
2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subp(kScratchRegister, args.GetArgumentOperand(2));
263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
263744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (FLAG_debug_code) {
263844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ movl(rax, Immediate(kWordBeforeResultValue));
263944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!ReturnTrueFalseObject()) {
2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Set(rax, 0);
264444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
264544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) *
2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         kPointerSize);
264880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
264980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&is_not_instance);
265044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!HasCallSiteInlineCheck()) {
265144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // We have to store a non-zero value in the cache.
265244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex);
2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (ReturnTrueFalseObject()) {
2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ LoadRoot(rax, Heap::kFalseValueRootIndex);
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
265644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else {
265744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Store offset of false in the root array at the inline check site.
26583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int false_offset = 0x100 +
26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias;
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assert it is a 1-byte signed value.
2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(false_offset >= 0 && false_offset < 0x100);
26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ movl(rax, Immediate(false_offset));
2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movq(kScratchRegister, StackOperandForReturnAddress(0));
2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subp(kScratchRegister, args.GetArgumentOperand(2));
266544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax);
266644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (FLAG_debug_code) {
266744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ movl(rax, Immediate(kWordBeforeResultValue));
266844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax);
2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov);
267044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
267144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) *
2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         kPointerSize);
267480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
267580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Slow-case: Go through the JavaScript implementation.
267680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&slow);
2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!ReturnTrueFalseObject()) {
2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Tail call the builtin which returns 0 or 1.
2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!HasArgsInRegisters());
2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (HasCallSiteInlineCheck()) {
2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Remove extra value from the stack.
2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PopReturnAddressTo(rcx);
2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Pop(rax);
2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ PushReturnAddressFrom(rcx);
2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Call the builtin and convert 0/1 to true/false.
2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    {
2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FrameScope scope(masm, StackFrame::INTERNAL);
2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(object);
2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(function);
2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label true_value, done;
2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testq(rax, rax);
2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(zero, &true_value, Label::kNear);
2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(rax, Heap::kFalseValueRootIndex);
2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ jmp(&done, Label::kNear);
2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&true_value);
2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(rax, Heap::kTrueValueRootIndex);
2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) *
2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           kPointerSize);
270580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
270680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
270780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
270880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
270980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// -------------------------------------------------------------------------
271080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// StringCharCodeAtGenerator
271180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
271280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
271380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If the receiver is a smi trigger the non-string case.
271480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfSmi(object_, receiver_not_string_);
271580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
271680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Fetch the instance type of the receiver into result register.
2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset));
271880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
271980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If the receiver is not a string trigger the non-string case.
272080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ testb(result_, Immediate(kIsNotStringMask));
272180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_zero, receiver_not_string_);
272280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
272380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If the index is non-smi trigger the non-smi case.
272480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfNotSmi(index_, &index_not_smi_);
272580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&got_smi_index_);
272680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
272780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check for index out of range.
27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiCompare(index_, FieldOperand(object_, String::kLengthOffset));
272980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(above_equal, index_out_of_range_);
273080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiToInteger32(index_, index_);
273280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  StringCharLoadGenerator::Generate(
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm, object_, index_, result_, &call_runtime_);
273569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
273680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Integer32ToSmi(result_, result_);
273780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&exit_);
273880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
273980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
274080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
274180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharCodeAtGenerator::GenerateSlow(
27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const RuntimeCallHelper& call_helper) {
2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
274580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Factory* factory = masm->isolate()->factory();
274780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Index is not a smi.
274880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&index_not_smi_);
274980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If index is a heap number, try converting it to an integer.
2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CheckMap(index_,
2751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              factory->heap_number_map(),
2752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              index_not_number_,
2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              DONT_DO_SMI_CHECK);
275480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  call_helper.BeforeCall(masm);
2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(object_);
2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(index_);  // Consumed by runtime conversion function.
275780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
275880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
275980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
276180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // NumberToSmi discards numbers that are not exact integers.
276280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ CallRuntime(Runtime::kNumberToSmi, 1);
276380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!index_.is(rax)) {
276580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Save the conversion result before the pop instructions below
276680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // have a chance to overwrite it.
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(index_, rax);
276880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(object_);
277080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Reload the instance type.
2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(result_, FieldOperand(object_, HeapObject::kMapOffset));
277280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movzxbl(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
277380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  call_helper.AfterCall(masm);
277480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If index is still not a smi, it must be out of range.
27753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfNotSmi(index_, index_out_of_range_);
277680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Otherwise, return to the fast path.
277780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&got_smi_index_);
277880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
277980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Call runtime. We get here when the receiver is a string and the
278080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // index is a number, but the code of getting the actual character
278180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // is too complex (e.g., when the string needs to be flattened).
278280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&call_runtime_);
278380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  call_helper.BeforeCall(masm);
2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(object_);
27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Integer32ToSmi(index_, index_);
2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(index_);
2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kStringCharCodeAtRT, 2);
278880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!result_.is(rax)) {
2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(result_, rax);
279080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
279180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  call_helper.AfterCall(masm);
279280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&exit_);
279380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
279580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
279680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
279780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
279880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// -------------------------------------------------------------------------
279980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// StringCharFromCodeGenerator
280080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
280180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
280280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Fast case of Heap::LookupSingleCharacterStringFromCode.
280380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ JumpIfNotSmi(code_, &slow_case_);
2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiCompare(code_, Smi::FromInt(String::kMaxOneByteCharCode));
280580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(above, &slow_case_);
280680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
280780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
280880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  SmiIndex index = masm->SmiToIndex(kScratchRegister, code_, kPointerSizeLog2);
2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(result_, FieldOperand(result_, index.reg, index.scale,
281080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                FixedArray::kHeaderSize));
281180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
281280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(equal, &slow_case_);
281380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&exit_);
281480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
281580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
281680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
281780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCharFromCodeGenerator::GenerateSlow(
28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const RuntimeCallHelper& call_helper) {
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
282180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
282280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&slow_case_);
282380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  call_helper.BeforeCall(masm);
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(code_);
282580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ CallRuntime(Runtime::kCharFromCode, 1);
282680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (!result_.is(rax)) {
2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(result_, rax);
282880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
282980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  call_helper.AfterCall(masm);
283080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ jmp(&exit_);
283180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
283380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
283480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
283580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
283680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
283780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Register dest,
283880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Register src,
283980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          Register count,
2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          String::Encoding encoding) {
284180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Nothing to do for zero characters.
2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
284380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ testl(count, count);
2844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(zero, &done, Label::kNear);
284580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
284680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Make count the number of bytes to copy.
2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (encoding == String::TWO_BYTE_ENCODING) {
284880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    STATIC_ASSERT(2 == sizeof(uc16));
284980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ addl(count, count);
285080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
285180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
285280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Copy remaining characters.
285380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label loop;
285480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&loop);
285580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movb(kScratchRegister, Operand(src, 0));
285680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movb(Operand(dest, 0), kScratchRegister);
2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ incp(src);
2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ incp(dest);
285980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ decl(count);
286080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(not_zero, &loop);
286180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
286280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&done);
286380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
286480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
286580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
286680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid SubStringStub::Generate(MacroAssembler* masm) {
286780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label runtime;
286880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
286980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Stack frame on entry.
2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[0]  : return address
2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[8]  : to
2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[16] : from
2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[24] : string
287480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum SubStringStubArgumentIndices {
2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STRING_ARGUMENT_INDEX,
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FROM_ARGUMENT_INDEX,
2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TO_ARGUMENT_INDEX,
2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SUB_STRING_ARGUMENT_COUNT
2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, SUB_STRING_ARGUMENT_COUNT,
2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              ARGUMENTS_DONT_CONTAIN_RECEIVER);
288480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
288580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Make sure first argument is a string.
2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, args.GetArgumentOperand(STRING_ARGUMENT_INDEX));
288780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  STATIC_ASSERT(kSmiTag == 0);
288880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ testl(rax, Immediate(kSmiTagMask));
288980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(zero, &runtime);
289080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
289180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ j(NegateCondition(is_string), &runtime);
289280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
289380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rax: string
289480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rbx: instance type
289580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Calculate length of sub string using the smi values.
2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, args.GetArgumentOperand(TO_ARGUMENT_INDEX));
2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, args.GetArgumentOperand(FROM_ARGUMENT_INDEX));
2898f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  __ JumpUnlessBothNonNegativeSmi(rcx, rdx, &runtime);
289980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
29000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ SmiSub(rcx, rcx, rdx);  // Overflow doesn't happen.
2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rcx, FieldOperand(rax, String::kLengthOffset));
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label not_original_string;
2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Shorter than original string's length: an actual substring.
2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(below, &not_original_string, Label::kNear);
2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Longer than original string's length or negative: unsafe arguments.
2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(above, &runtime);
2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return original string.
2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Counters* counters = isolate()->counters();
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ IncrementCounter(counters->sub_string_native(), 1);
2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&not_original_string);
291280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label single_char;
2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiCompare(rcx, Smi::FromInt(1));
2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &single_char);
291680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rcx, rcx);
29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rax: string
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rbx: instance type
29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rcx: sub string length
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdx: from index (smi)
29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Deal with different string types: update the index if necessary
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and put the underlying string into edi.
29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label underlying_unpacked, sliced_string, seq_or_external_string;
29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the string is not indirect, it can only be sequential or external.
29273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kIsIndirectStringMask != 0);
29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testb(rbx, Immediate(kIsIndirectStringMask));
29303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(zero, &seq_or_external_string, Label::kNear);
29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testb(rbx, Immediate(kSlicedNotConsMask));
29333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_zero, &sliced_string, Label::kNear);
29343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cons string.  Check whether it is flat, then fetch first part.
29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Flat cons strings have an empty second part.
29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset),
2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 Heap::kempty_stringRootIndex);
29383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &runtime);
2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rax, ConsString::kFirstOffset));
29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update instance type.
2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
294280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&underlying_unpacked, Label::kNear);
29443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&sliced_string);
29463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sliced string.  Fetch parent and correct start index by offset.
2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rdx, FieldOperand(rax, SlicedString::kOffsetOffset));
2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rax, SlicedString::kParentOffset));
29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update instance type.
2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rdi, HeapObject::kMapOffset));
29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&underlying_unpacked, Label::kNear);
29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&seq_or_external_string);
29553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sequential or external string.  Just move string to the correct register.
2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, rax);
29573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&underlying_unpacked);
295980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2960589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (FLAG_string_slices) {
2961589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Label copy_routine;
29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdi: underlying subject string
29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rbx: instance type of underlying subject string
29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rdx: adjusted start index (smi)
29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rcx: length
2966589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // If coming from the make_two_character_string path, the string
2967589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // is too short to be sliced anyways.
2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(rcx, Immediate(SlicedString::kMinLength));
2969589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Short slice.  Copy instead of slicing.
2970589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ j(less, &copy_routine);
2971589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Allocate new sliced string.  At this point we do not reload the instance
2972589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // type including the string encoding because we simply rely on the info
2973589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // provided by the original string.  It does not matter if the original
2974589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // string's encoding is wrong because we always have to recheck encoding of
2975589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // the newly created string's parent anyways due to externalized strings.
2976589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Label two_byte_slice, set_slice_header;
2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
2978589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
2979589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ testb(rbx, Immediate(kStringEncodingMask));
2980589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ j(zero, &two_byte_slice, Label::kNear);
2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ AllocateOneByteSlicedString(rax, rbx, r14, &runtime);
2982589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ jmp(&set_slice_header, Label::kNear);
2983589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ bind(&two_byte_slice);
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ AllocateTwoByteSlicedString(rax, rbx, r14, &runtime);
2985589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ bind(&set_slice_header);
2986589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ Integer32ToSmi(rcx, rcx);
2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(FieldOperand(rax, SlicedString::kLengthOffset), rcx);
2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(FieldOperand(rax, SlicedString::kHashFieldOffset),
2989589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch           Immediate(String::kEmptyHashField));
2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(FieldOperand(rax, SlicedString::kParentOffset), rdi);
2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(FieldOperand(rax, SlicedString::kOffsetOffset), rdx);
29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ IncrementCounter(counters->sub_string_native(), 1);
2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ret(3 * kPointerSize);
2994589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2995589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    __ bind(&copy_routine);
2996589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
299780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdi: underlying subject string
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rbx: instance type of underlying subject string
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rdx: adjusted start index (smi)
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rcx: length
30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The subject string can only be external or sequential string of either
30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // encoding at this point.
30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label two_byte_sequential, sequential_string;
30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kExternalStringTag != 0);
30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kSeqStringTag == 0);
30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testb(rbx, Immediate(kExternalStringTag));
30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(zero, &sequential_string);
30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle external string.
30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Rule out short external strings.
3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kShortExternalStringTag != 0);
30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testb(rbx, Immediate(kShortExternalStringMask));
30143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_zero, &runtime);
3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rdi, ExternalString::kResourceDataOffset));
30163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Move the pointer so that offset-wise, it looks like a sequential string.
3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rdi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
30203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&sequential_string);
3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ testb(rbx, Immediate(kStringEncodingMask));
30233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(zero, &two_byte_sequential);
302480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
302580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Allocate the result.
3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AllocateOneByteString(rax, rcx, r11, r14, r15, &runtime);
302780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
302880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rax: result string
302980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx: result string length
30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {  // Locate character of sub string start.
30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1);
3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SeqOneByteString::kHeaderSize - kHeapObjectTag));
303485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
30353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Locate first character of result.
3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdi, FieldOperand(rax, SeqOneByteString::kHeaderSize));
303780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
303880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rax: result string
303980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx: result length
3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r14: first character of result
304180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rsi: character of sub string start
3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringHelper::GenerateCopyCharacters(
3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm, rdi, r14, rcx, String::ONE_BYTE_ENCODING);
304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->sub_string_native(), 1);
3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
304680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&two_byte_sequential);
304880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Allocate the result.
30493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ AllocateTwoByteString(rax, rcx, r11, r14, r15, &runtime);
305080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
305180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rax: result string
305280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx: result string length
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {  // Locate character of sub string start.
30543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2);
3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale,
3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        SeqOneByteString::kHeaderSize - kHeapObjectTag));
305785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Locate first character of result.
3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize));
306080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
306180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rax: result string
306280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rcx: result length
306380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // rdi: first character of result
3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r14: character of sub string start
3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringHelper::GenerateCopyCharacters(
3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm, rdi, r14, rcx, String::TWO_BYTE_ENCODING);
306744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->sub_string_native(), 1);
3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
306980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
307080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Just jump to runtime to create the sub string.
307180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&runtime);
307280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ TailCallRuntime(Runtime::kSubString, 3, 1);
3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&single_char);
3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rax: string
3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx: instance type
3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rcx: sub string length (smi)
3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdx: from index (smi)
3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringCharAtGenerator generator(
3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rax, rdx, rcx, rax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  generator.GenerateFast(masm);
3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  generator.SkipSlow(masm, &runtime);
308480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
308580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
308680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                   Register left,
3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                   Register right,
3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                   Register scratch1,
3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                   Register scratch2) {
3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register length = scratch1;
3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compare lengths.
3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label check_zero_length;
3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(length, FieldOperand(left, String::kLengthOffset));
3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SmiCompare(length, FieldOperand(right, String::kLengthOffset));
3098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(equal, &check_zero_length, Label::kNear);
3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Move(rax, Smi::FromInt(NOT_EQUAL));
3100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the length is zero.
3103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label compare_chars;
3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&check_zero_length);
3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SmiTest(length);
3107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, &compare_chars, Label::kNear);
3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Move(rax, Smi::FromInt(EQUAL));
3109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compare characters.
3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&compare_chars);
3113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label strings_not_equal;
3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2,
3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  &strings_not_equal, Label::kNear);
3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Characters are equal.
3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Move(rax, Smi::FromInt(EQUAL));
3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Characters are not equal.
3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&strings_not_equal);
3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Move(rax, Smi::FromInt(NOT_EQUAL));
3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringHelper::GenerateCompareFlatOneByteStrings(
3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, Register left, Register right, Register scratch1,
3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch2, Register scratch3, Register scratch4) {
313180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Ensure that you can always subtract a string length from a non-negative
313280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // number (e.g. another length).
313380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
313480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
313580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Find minimum length and length difference.
3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch1, FieldOperand(left, String::kLengthOffset));
3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch4, scratch1);
313880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ SmiSub(scratch4,
313980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen            scratch4,
31400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            FieldOperand(right, String::kLengthOffset));
314180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Register scratch4 now holds left.length - right.length.
314280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const Register length_difference = scratch4;
3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label left_shorter;
3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(less, &left_shorter, Label::kNear);
314580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The right string isn't longer that the left one.
314680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Get the right string's length by subtracting the (non-negative) difference
314780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // from the left string's length.
31480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ SmiSub(scratch1, scratch1, length_difference);
314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&left_shorter);
315080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Register scratch1 now holds Min(left.length, right.length).
315180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const Register min_length = scratch1;
315280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label compare_lengths;
315480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // If min-length is zero, go directly to comparing lengths.
315580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ SmiTest(min_length);
3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(zero, &compare_lengths, Label::kNear);
315780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compare loop.
3159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label result_not_equal;
3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateOneByteCharsCompareLoop(
3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm, left, right, min_length, scratch2, &result_not_equal,
3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // In debug-code mode, SmiTest below might push
3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // the target label outside the near range.
3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label::kFar);
316580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
316680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Completed loop without finding different characters.
316780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Compare lengths (precomputed).
316880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&compare_lengths);
316980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ SmiTest(length_difference);
3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label length_not_equal;
3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &length_not_equal, Label::kNear);
317280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
317380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Result is EQUAL.
317480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Move(rax, Smi::FromInt(EQUAL));
317580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret(0);
317680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label result_greater;
3178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label result_less;
3179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&length_not_equal);
3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(greater, &result_greater, Label::kNear);
3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&result_less, Label::kNear);
318280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&result_not_equal);
318380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Unequal comparison of left to right, either character or length.
3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(above, &result_greater, Label::kNear);
3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&result_less);
318680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
318780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Result is LESS.
318880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Move(rax, Smi::FromInt(LESS));
318980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret(0);
319080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Result is GREATER.
319280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&result_greater);
319380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Move(rax, Smi::FromInt(GREATER));
319480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret(0);
319580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
319680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
319780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StringHelper::GenerateOneByteCharsCompareLoop(
3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, Register left, Register right, Register length,
3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register scratch, Label* chars_not_equal, Label::Distance near_jump) {
3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Change index to run from -length to -1 by adding length to string
3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // start. This means that loop ends when index reaches zero, which
3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // doesn't need an additional compare.
3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SmiToInteger32(length, length);
3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(left,
3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(left, length, times_1, SeqOneByteString::kHeaderSize));
3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(right,
3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         FieldOperand(right, length, times_1, SeqOneByteString::kHeaderSize));
3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ negq(length);
3210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register index = length;  // index = -length;
3211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Compare loop.
3213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label loop;
3214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&loop);
3215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ movb(scratch, Operand(left, index, times_1, 0));
3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ cmpb(scratch, Operand(right, index, times_1, 0));
3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, chars_not_equal, near_jump);
32183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ incq(index);
3219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, &loop);
3220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
322380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StringCompareStub::Generate(MacroAssembler* masm) {
322480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label runtime;
322580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
322680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Stack frame on entry.
3227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[0]  : return address
3228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[8]  : right string
3229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[16] : left string
323080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, args.GetArgumentOperand(0));  // left
3233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rax, args.GetArgumentOperand(1));  // right
323480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
323580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Check for identity.
3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_same;
3237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(rdx, rax);
3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &not_same, Label::kNear);
323980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Move(rax, Smi::FromInt(EQUAL));
3240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Counters* counters = isolate()->counters();
324144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_compare_native(), 1);
324280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ ret(2 * kPointerSize);
324380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&not_same);
324580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both are sequential one-byte strings.
3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotBothSequentialOneByteStrings(rdx, rax, rcx, rbx, &runtime);
324880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Inline comparison of one-byte strings.
325044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  __ IncrementCounter(counters->string_compare_native(), 1);
325180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Drop arguments from the stack
3252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(rcx);
3253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(rsp, Immediate(2 * kPointerSize));
3254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(rcx);
3255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StringHelper::GenerateCompareFlatOneByteStrings(masm, rdx, rax, rcx, rbx, rdi,
3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  r8);
325780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
325880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
325980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // tagged as a small integer.
326080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&runtime);
326180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
326280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
326380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
3266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------- S t a t e -------------
3267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rdx    : left
3268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rax    : right
3269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0] : return address
3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------
3271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load rcx with the allocation site.  We stick an undefined dummy value here
3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and replace it with the real allocation site later when we instantiate this
3274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
3275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rcx, handle(isolate()->heap()->undefined_value()));
3276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure that we actually patched the allocation site.
3278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
3279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testb(rcx, Immediate(kSmiTagMask));
3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(not_equal, kExpectedAllocationSite);
3281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
3282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           isolate()->factory()->allocation_site_map());
3283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(equal, kExpectedAllocationSite);
3284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Tail call into the stub that handles binary operations with allocation
3287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // sites.
3288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BinaryOpWithAllocationSiteStub stub(isolate(), state());
3289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallStub(&stub);
3290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateSmis(MacroAssembler* masm) {
3294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(state() == CompareICState::SMI);
3295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear);
32971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (GetCondition() == equal) {
32991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // For equality we do not care about the sign of the result.
3300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subp(rax, rdx);
33011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
3302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Label done;
3303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ subp(rdx, rax);
3304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(no_overflow, &done, Label::kNear);
33051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Correct sign of result in case of overflow.
3306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ notp(rdx);
33071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&done);
3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rax, rdx);
33091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
33101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);
33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&miss);
33131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateMiss(masm);
3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateNumbers(MacroAssembler* masm) {
3318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(state() == CompareICState::NUMBER);
33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label generic_stub;
33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label unordered, maybe_undefined1, maybe_undefined2;
3322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (left() == CompareICState::SMI) {
3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfNotSmi(rdx, &miss);
3326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (right() == CompareICState::SMI) {
3328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfNotSmi(rax, &miss);
3329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
3330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load left and right operand.
3332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done, left, left_smi, right_smi;
3333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(rax, &right_smi, Label::kNear);
3334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareMap(rax, isolate()->factory()->heap_number_map());
33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &maybe_undefined1, Label::kNear);
3336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
3337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&left, Label::kNear);
3338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&right_smi);
3339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rcx, rax);  // Can't clobber rax yet.
3340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cvtlsi2sd(xmm1, rcx);
3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&left);
3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfSmi(rdx, &left_smi, Label::kNear);
3344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareMap(rdx, isolate()->factory()->heap_number_map());
33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &maybe_undefined2, Label::kNear);
33461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
3347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&done);
3348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&left_smi);
3349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rcx, rdx);  // Can't clobber rdx yet.
3350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Cvtlsi2sd(xmm0, rcx);
33511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
33531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compare operands
33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ucomisd(xmm0, xmm1);
33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Don't base result on EFLAGS when a NaN is involved.
3357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(parity_even, &unordered, Label::kNear);
33581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Return a result of -1, 0, or 1, based on EFLAGS.
33601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Performing mov, because xor would destroy the flag register.
33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movl(rax, Immediate(0));
33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movl(rcx, Immediate(0));
33631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ setcc(above, rax);  // Add one to zero if carry clear and not equal.
3364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sbbp(rax, rcx);  // Subtract one if below (aka. carry set).
33651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);
33661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&unordered);
33681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&generic_stub);
3369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CompareICStub stub(isolate(), op(), CompareICState::GENERIC,
3370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     CompareICState::GENERIC, CompareICState::GENERIC);
33711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
33721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&maybe_undefined1);
3374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Token::IsOrderedRelationalCompareOp(op())) {
3375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cmp(rax, isolate()->factory()->undefined_value());
33763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &miss);
3377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfSmi(rdx, &unordered);
33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx);
33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(not_equal, &maybe_undefined2, Label::kNear);
33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ jmp(&unordered);
33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&maybe_undefined2);
3384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (Token::IsOrderedRelationalCompareOp(op())) {
3385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cmp(rdx, isolate()->factory()->undefined_value());
33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ j(equal, &unordered);
33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
33891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&miss);
33901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateMiss(masm);
3391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) {
3395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(state() == CompareICState::INTERNALIZED_STRING);
3396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(GetCondition() == equal);
3397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Registers containing left and right operands respectively.
3399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register left = rdx;
3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register right = rax;
3401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tmp1 = rcx;
3402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register tmp2 = rbx;
3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both operands are heap objects.
3405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label miss;
3406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Condition cond = masm->CheckEitherSmi(left, right, tmp1);
3407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(cond, &miss, Label::kNear);
3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both operands are internalized strings.
3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset));
3411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset));
3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
3413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
3414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orp(tmp1, tmp2);
3416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
3417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &miss, Label::kNear);
3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Internalized strings are compared by identity.
3420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label done;
3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(left, right);
3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Make sure rax is non-zero. At this point input operands are
3423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // guaranteed to be non-zero.
3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(right.is(rax));
3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_equal, &done, Label::kNear);
3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(EQUAL == 0);
3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiTag == 0);
3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rax, Smi::FromInt(EQUAL));
3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ret(0);
3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&miss);
3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateMiss(masm);
3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) {
3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(state() == CompareICState::UNIQUE_NAME);
3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(GetCondition() == equal);
3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Registers containing left and right operands respectively.
3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register left = rdx;
3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register right = rax;
3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp1 = rcx;
3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp2 = rbx;
3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both operands are heap objects.
3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition cond = masm->CheckEitherSmi(left, right, tmp1);
3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(cond, &miss, Label::kNear);
3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both operands are unique names. This leaves the instance
3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // types loaded in tmp1 and tmp2.
3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset));
3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset));
3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotUniqueNameInstanceType(tmp1, &miss, Label::kNear);
3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotUniqueNameInstanceType(tmp2, &miss, Label::kNear);
3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Unique names are compared by identity.
3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label done;
3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(left, right);
3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Make sure rax is non-zero. At this point input operands are
3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // guaranteed to be non-zero.
3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(right.is(rax));
3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &done, Label::kNear);
3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(EQUAL == 0);
3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Move(rax, Smi::FromInt(EQUAL));
3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&done);
3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMiss(masm);
3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateStrings(MacroAssembler* masm) {
3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(state() == CompareICState::STRING);
3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
3483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool equality = Token::IsEqualityOp(op());
34853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Registers containing left and right operands respectively.
3487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register left = rdx;
3488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register right = rax;
3489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp1 = rcx;
3490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp2 = rbx;
3491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Register tmp3 = rdi;
3492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both operands are heap objects.
3494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Condition cond = masm->CheckEitherSmi(left, right, tmp1);
3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(cond, &miss);
3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check that both operands are strings. This leaves the instance
3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // types loaded in tmp1 and tmp2.
3499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp1, FieldOperand(left, HeapObject::kMapOffset));
3500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp2, FieldOperand(right, HeapObject::kMapOffset));
3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
3502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
3503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(tmp3, tmp1);
3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kNotStringTag != 0);
3505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orp(tmp3, tmp2);
3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ testb(tmp3, Immediate(kIsNotStringMask));
3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, &miss);
3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Fast check for identical strings.
3510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label not_same;
3511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpp(left, right);
3512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &not_same, Label::kNear);
3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(EQUAL == 0);
3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  STATIC_ASSERT(kSmiTag == 0);
3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Move(rax, Smi::FromInt(EQUAL));
3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(0);
3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle not identical strings.
3519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&not_same);
3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both strings are internalized strings. If they are, we're done
3522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // because we already know they are not identical. We also know they are both
3523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // strings.
35243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (equality) {
35253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label do_compare;
3526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kInternalizedTag == 0);
3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ orp(tmp1, tmp2);
3528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testb(tmp1, Immediate(kIsNotInternalizedMask));
3529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &do_compare, Label::kNear);
35303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Make sure rax is non-zero. At this point input operands are
35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // guaranteed to be non-zero.
3532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(right.is(rax));
35333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
35343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&do_compare);
35353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Check that both strings are sequential one-byte.
3538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label runtime;
3539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ JumpIfNotBothSequentialOneByteStrings(left, right, tmp1, tmp2, &runtime);
3540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compare flat one-byte strings. Returns when done.
35423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (equality) {
3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1,
3544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  tmp2);
35453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
3546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StringHelper::GenerateCompareFlatOneByteStrings(
35473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm, left, right, tmp1, tmp2, tmp3, kScratchRegister);
35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Handle more complex cases in runtime.
3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&runtime);
3552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(tmp1);
3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(left);
3554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(right);
3555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(tmp1);
35563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (equality) {
35573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
35583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
35593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
35603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&miss);
3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  GenerateMiss(masm);
3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateObjects(MacroAssembler* masm) {
3568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(state() == CompareICState::OBJECT);
3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label miss;
35701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Condition either_smi = masm->CheckEitherSmi(rdx, rax);
3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(either_smi, &miss, Label::kNear);
35721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx);
3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss, Label::kNear);
35751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
3576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_equal, &miss, Label::kNear);
35771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(GetCondition() == equal);
3579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rax, rdx);
35801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);
35811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
35821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&miss);
35831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GenerateMiss(masm);
3584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
3585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateKnownObjects(MacroAssembler* masm) {
35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label miss;
35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Condition either_smi = masm->CheckEitherSmi(rdx, rax);
35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(either_smi, &miss, Label::kNear);
3591c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
3592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset));
3593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
35943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rcx, known_map_);
35953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &miss, Label::kNear);
35963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Cmp(rbx, known_map_);
35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ j(not_equal, &miss, Label::kNear);
35981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(rax, rdx);
36003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
360185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&miss);
36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateMiss(masm);
36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CompareICStub::GenerateMiss(MacroAssembler* masm) {
36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Call the runtime system in a fresh internal frame.
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalReference miss =
3611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate());
36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FrameScope scope(masm, StackFrame::INTERNAL);
3614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rdx);
3615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rax);
3616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rdx);
3617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(rax);
3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(Smi::FromInt(op()));
36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallExternalReference(miss, 3);
36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Compute the entry point of the rewritten stub.
3622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(rdi, FieldOperand(rax, Code::kHeaderSize));
3623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(rax);
3624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(rdx);
36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
36261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Do a tail call to the rewritten stub.
36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ jmp(rdi);
36291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
36301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
36311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
3633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Label* miss,
3634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Label* done,
3635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Register properties,
3636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Handle<Name> name,
3637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Register r0) {
3638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(name->IsUniqueName());
3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If names of slots in range from 1 to kProbes - 1 for the hash value are
3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // not equal to the name and kProbes-th slot is not used (its name is the
3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // undefined value), it guarantees the hash table doesn't contain the
3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // property. It's true even if some slots represent deleted properties
36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (their names are the hole value).
3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < kInlinedProbes; i++) {
3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // r0 points to properties hash.
3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register index = r0;
3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Capacity is smi 2^n.
3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ decl(index);
3651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andp(index,
3652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Immediate(name->Hash() + NameDictionary::GetProbeOffset(i)));
3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Scale the index by multiplying by the entry size.
3655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(NameDictionary::kEntrySize == 3);
3656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(index, Operand(index, index, times_2, 0));  // index *= 3.
3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Register entity_name = r0;
3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Having undefined at this place means the name is not contained.
3660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(kSmiTagSize, 1);
3661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(entity_name, Operand(properties,
3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 index,
3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 times_pointer_size,
3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                 kElementsStartOffset - kHeapObjectTag));
3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, done);
3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Stop if found the property.
3669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cmp(entity_name, Handle<Name>(name));
3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, miss);
3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label good;
36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check for the hole and skip.
36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex);
3675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, &good, Label::kNear);
36763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Check if the entry name is not a unique name.
3678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfNotUniqueNameInstanceType(
3680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FieldOperand(entity_name, Map::kInstanceTypeOffset), miss);
3681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&good);
3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NameDictionaryLookupStub stub(masm->isolate(), properties, r0, r0,
3685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                NEGATIVE_LOOKUP);
3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Push(Handle<Object>(name));
3687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Immediate(name->Hash()));
36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallStub(&stub);
3689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(r0, r0);
3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(not_zero, miss);
3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(done);
3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Probe the name dictionary in the |elements| register. Jump to the
3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// |done| label if a property with the given name is found leaving the
3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// index into the dictionary in |r1|. Jump to the |miss| label
3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// otherwise.
3699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Label* miss,
3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Label* done,
3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Register elements,
3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Register name,
3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Register r0,
3705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                      Register r1) {
3706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!elements.is(r0));
3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!elements.is(r1));
3708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!name.is(r0));
3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!name.is(r1));
3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AssertName(name);
3712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
3714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ decl(r0);
3715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = 0; i < kInlinedProbes; i++) {
3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
3718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movl(r1, FieldOperand(name, Name::kHashFieldOffset));
3719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ shrl(r1, Immediate(Name::kHashShift));
3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i > 0) {
3721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addl(r1, Immediate(NameDictionary::GetProbeOffset(i)));
3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andp(r1, r0);
3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Scale the index by multiplying by the entry size.
3726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(NameDictionary::kEntrySize == 3);
3727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(r1, Operand(r1, r1, times_2, 0));  // r1 = r1 * 3
3728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Check if the key is identical to the name.
3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(name, Operand(elements, r1, times_pointer_size,
3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          kElementsStartOffset - kHeapObjectTag));
3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, done);
3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NameDictionaryLookupStub stub(masm->isolate(), elements, r0, r1,
3736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                POSITIVE_LOOKUP);
3737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(name);
3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movl(r0, FieldOperand(name, Name::kHashFieldOffset));
3739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ shrl(r0, Immediate(Name::kHashShift));
3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(r0);
3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ CallStub(&stub);
3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(r0, r0);
3744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ j(zero, miss);
3745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ jmp(done);
3746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // we cannot call anything that could cause a GC from this stub.
3752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Stack frame on entry:
3753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[0 * kPointerSize] : return address.
3754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[1 * kPointerSize] : key's hash.
3755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  rsp[2 * kPointerSize] : key.
3756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Registers:
3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  dictionary_: NameDictionary to probe.
3758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  result_: used as scratch.
3759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  index_: will hold an index of entry if lookup is successful.
3760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //          might alias with result_.
3761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Returns:
3762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  //  result_ is zero if lookup failed, non zero otherwise.
3763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = result();
3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(scratch, FieldOperand(dictionary(), kCapacityOffset));
3769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ decl(scratch);
3770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(scratch);
3771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If names of slots in range from 1 to kProbes - 1 for the hash value are
3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // not equal to the name and kProbes-th slot is not used (its name is the
3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // undefined value), it guarantees the hash table doesn't contain the
3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // property. It's true even if some slots represent deleted properties
3776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // (their names are the null value).
3777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER,
3778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              kPointerSize);
3779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  for (int i = kInlinedProbes; i < kTotalProbes; i++) {
3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Compute the masked index: (hash + i + i * i) & mask.
3781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(scratch, args.GetArgumentOperand(1));
3782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (i > 0) {
3783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
3784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ andp(scratch, Operand(rsp, 0));
3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Scale the index by multiplying by the entry size.
3788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(NameDictionary::kEntrySize == 3);
3789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ leap(index(), Operand(scratch, scratch, times_2, 0));  // index *= 3.
3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Having undefined at this place means the name is not contained.
3792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(scratch, Operand(dictionary(), index(), times_pointer_size,
3793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                             kElementsStartOffset - kHeapObjectTag));
3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Cmp(scratch, isolate()->factory()->undefined_value());
3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &not_in_dictionary);
3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Stop if found the property.
3799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpp(scratch, args.GetArgumentOperand(0));
3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ j(equal, &in_dictionary);
3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) {
3803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // If we hit a key that is not a unique name during negative
3804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // lookup we have to bailout as this key might be equal to the
3805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      // key we are looking for.
3806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Check if the entry name is not a unique name.
3808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
3809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ JumpIfNotUniqueNameInstanceType(
3810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          FieldOperand(scratch, Map::kInstanceTypeOffset),
3811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          &maybe_in_dictionary);
3812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
3813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&maybe_in_dictionary);
3816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // If we are doing negative lookup then probing failure should be
3817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // treated as a lookup success. For positive lookup probing failure
3818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // should be treated as lookup failure.
3819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode() == POSITIVE_LOOKUP) {
3820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(scratch, Immediate(0));
3821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ Drop(1);
3822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    __ ret(2 * kPointerSize);
3823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
3824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&in_dictionary);
3826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, Immediate(1));
3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(1);
3828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(2 * kPointerSize);
3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ bind(&not_in_dictionary);
3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, Immediate(0));
3832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ Drop(1);
3833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ret(2 * kPointerSize);
3834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
3835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
3837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
3838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate) {
3839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs);
3840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  stub1.GetCode();
3841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreBufferOverflowStub stub2(isolate, kSaveFPRegs);
3842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  stub2.GetCode();
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Takes the input in 3 registers: address_ value_ and object_.  A pointer to
38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the value has just been written into the object, now this stub makes sure
38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// we keep the GC informed.  The word in the object where the value has been
38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// written is in the address register.
38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::Generate(MacroAssembler* masm) {
38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip_to_incremental_noncompacting;
38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label skip_to_incremental_compacting;
38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The first two instructions are generated with labels so as to get the
38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // offset fixed up correctly by the bind(Label*) call.  We patch it back and
38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // forth between a compare instructions (a nop in this position) and the
38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // real branch when we start and stop incremental heap marking.
38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // See RecordWriteStub::Patch for details.
38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&skip_to_incremental_noncompacting, Label::kNear);
38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&skip_to_incremental_compacting, Label::kFar);
38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (remembered_set_action() == EMIT_REMEMBERED_SET) {
3863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           MacroAssembler::kReturnAtEnd);
38653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
38663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&skip_to_incremental_noncompacting);
38703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateIncremental(masm, INCREMENTAL);
38713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&skip_to_incremental_compacting);
38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GenerateIncremental(masm, INCREMENTAL_COMPACTION);
38743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
38763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Will be checked in IncrementalMarking::ActivateGeneratedStub.
38773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->set_byte_at(0, kTwoByteNopInstruction);
38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->set_byte_at(2, kFiveByteNopInstruction);
38793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
38803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  regs_.Save(masm);
38843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (remembered_set_action() == EMIT_REMEMBERED_SET) {
38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label dont_need_remembered_set;
38873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(regs_.scratch0(), Operand(regs_.address(), 0));
38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ JumpIfNotInNewSpace(regs_.scratch0(),
38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           regs_.scratch0(),
38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           &dont_need_remembered_set);
38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CheckPageFlag(regs_.object(),
38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     regs_.scratch0(),
38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     1 << MemoryChunk::SCAN_ON_SCAVENGE,
38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     not_zero,
38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     &dont_need_remembered_set);
38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // First notify the incremental marker if necessary, then update the
39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // remembered set.
39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckNeedsToInformIncrementalMarker(
39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode);
3903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InformIncrementalMarker(masm);
39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    regs_.Restore(masm);
3905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           MacroAssembler::kReturnAtEnd);
39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&dont_need_remembered_set);
39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckNeedsToInformIncrementalMarker(
39123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InformIncrementalMarker(masm);
39143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  regs_.Restore(masm);
39153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
39163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) {
3920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode());
39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Register address =
3922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address();
3923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!address.is(regs_.object()));
3924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!address.is(arg_reg_1));
39253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Move(address, regs_.address());
3926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(arg_reg_1, regs_.object());
3927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(gc) Can we just set address arg2 in the beginning?
3928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(arg_reg_2, address);
3929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadAddress(arg_reg_3,
3930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 ExternalReference::isolate_address(isolate()));
39313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int argument_count = 3;
39323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AllowExternalCallThatCantCauseGC scope(masm);
39343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PrepareCallCFunction(argument_count);
3935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallCFunction(
3936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::incremental_marking_record_write_function(isolate()),
3937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      argument_count);
3938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode());
39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
39403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RecordWriteStub::CheckNeedsToInformIncrementalMarker(
39433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MacroAssembler* masm,
39443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    OnNoNeedToInformIncrementalMarker on_no_need,
39453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Mode mode) {
39463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label on_black;
39473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label need_incremental;
39483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label need_incremental_pop_object;
39493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(regs_.scratch0(), Immediate(~Page::kPageAlignmentMask));
3951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ andp(regs_.scratch0(), regs_.object());
3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(regs_.scratch1(),
3953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(regs_.scratch0(),
3954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 MemoryChunk::kWriteBarrierCounterOffset));
3955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(regs_.scratch1(), Immediate(1));
3956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(regs_.scratch0(),
3957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 MemoryChunk::kWriteBarrierCounterOffset),
3958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         regs_.scratch1());
3959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(negative, &need_incremental);
3960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Let's look at the color of the object:  If it is not black we don't have
39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to inform the incremental marker.
39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfBlack(regs_.object(),
39643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 regs_.scratch0(),
39653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 regs_.scratch1(),
39663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &on_black,
39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 Label::kNear);
39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  regs_.Restore(masm);
39703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
3971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
39723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           MacroAssembler::kReturnAtEnd);
39733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
39743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
39753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&on_black);
39783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the value from the slot.
3980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(regs_.scratch0(), Operand(regs_.address(), 0));
39813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (mode == INCREMENTAL_COMPACTION) {
39833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Label ensure_not_white;
39843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CheckPageFlag(regs_.scratch0(),  // Contains value.
39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     regs_.scratch1(),  // Scratch.
39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     MemoryChunk::kEvacuationCandidateMask,
39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     zero,
39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     &ensure_not_white,
39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Label::kNear);
39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CheckPageFlag(regs_.object(),
39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     regs_.scratch1(),  // Scratch.
39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     MemoryChunk::kSkipEvacuationSlotsRecordingMask,
39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     zero,
39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     &need_incremental);
39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ bind(&ensure_not_white);
39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We need an extra register for this, so we push the object register
40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // temporarily.
4003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(regs_.object());
40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ EnsureNotWhite(regs_.scratch0(),  // The value.
40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    regs_.scratch1(),  // Scratch.
40063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    regs_.object(),  // Scratch.
40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    &need_incremental_pop_object,
40083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    Label::kNear);
4009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(regs_.object());
40103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  regs_.Restore(masm);
40123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
4013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
40143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           MacroAssembler::kReturnAtEnd);
40153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
40163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ ret(0);
40173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&need_incremental_pop_object);
4020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(regs_.object());
40213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&need_incremental);
40233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fall through when we need to inform the incremental marker.
40253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
40263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
40293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ----------- S t a t e -------------
4030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rax     : element value to store
4031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rcx     : element index as smi
4032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0]  : return address
4033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[8]  : array literal index in function
4034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[16] : array literal
4035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // clobbers rbx, rdx, rdi
40363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // -----------------------------------
40373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label element_done;
40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label double_elements;
40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label smi_element;
40413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label slow_elements;
40423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label fast_elements;
40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get array literal index, array literal and its map.
4045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER);
4046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, args.GetArgumentOperand(1));
4047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, args.GetArgumentOperand(0));
4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdi, FieldOperand(rbx, JSObject::kMapOffset));
4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CheckFastElements(rdi, &double_elements);
40513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS
40533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ JumpIfSmi(rax, &smi_element);
4054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CheckFastSmiElements(rdi, &fast_elements);
40553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Store into the array literal requires a elements transition. Call into
40573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the runtime.
40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&slow_elements);
4060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(rdi);
4061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rbx);
4062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rcx);
4063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rax);
4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(rdx);
4067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(rdi);
40683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
40693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
40713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&fast_elements);
40723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiToInteger32(kScratchRegister, rcx);
4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size,
40753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           FixedArrayBase::kHeaderSize));
4076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(Operand(rcx, 0), rax);
40773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update the write barrier for the array store.
40783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ RecordWrite(rbx, rcx, rax,
40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 kDontSaveFPRegs,
40803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 EMIT_REMEMBERED_SET,
40813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 OMIT_SMI_CHECK);
40823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
40833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or
4085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FAST_*_ELEMENTS, and value is Smi.
40863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&smi_element);
40873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiToInteger32(kScratchRegister, rcx);
4088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
4089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(FieldOperand(rbx, kScratchRegister, times_pointer_size,
40903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                       FixedArrayBase::kHeaderSize), rax);
40913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
40923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
40933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
40943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&double_elements);
40953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(r9, FieldOperand(rbx, JSObject::kElementsOffset));
40973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ SmiToInteger32(r11, rcx);
40983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ StoreNumberToDoubleElements(rax,
40993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 r9,
41003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 r11,
41013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 xmm0,
41023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 &slow_elements);
41033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ret(0);
41043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
41053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
4108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub ces(isolate(), 1, kSaveFPRegs);
4109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int parameter_count_offset =
4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rbx, MemOperand(rbp, parameter_count_offset));
4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(rcx);
4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int additional_offset =
4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0;
4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset));
4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(rcx);  // Return to IC Miss stub, continuation still on stack.
4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadICTrampolineStub::Generate(MacroAssembler* masm) {
4123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister());
4124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VectorLoadStub stub(isolate(), state());
4125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
4126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
4130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister());
4131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VectorKeyedLoadStub stub(isolate());
4132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
4133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (masm->isolate()->function_entry_hook() != NULL) {
4138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProfileEntryHookStub stub(masm->isolate());
4139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    masm->CallStub(&stub);
4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) {
4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This stub can be called from essentially anywhere, so it needs to save
4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // all volatile and callee-save registers.
4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const size_t kNumSavedRegisters = 2;
4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pushq(arg_reg_1);
4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pushq(arg_reg_2);
4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate the original stack pointer and store it in the second arg.
4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(arg_reg_2,
4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(rsp, kNumSavedRegisters * kRegisterSize + kPCOnStackSize));
4154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Calculate the function address to the first arg.
4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(arg_reg_1, Operand(rsp, kNumSavedRegisters * kRegisterSize));
4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ subp(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength));
4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Save the remainder of the volatile registers.
4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->PushCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2);
4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Call the entry hook function.
4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(rax, FUNCTION_ADDR(isolate()->function_entry_hook()),
4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Assembler::RelocInfoNone());
4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AllowExternalCallThatCantCauseGC scope(masm);
4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kArgumentCount = 2;
4169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PrepareCallCFunction(kArgumentCount);
4170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallCFunction(rax, kArgumentCount);
4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Restore volatile regs.
4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm->PopCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2);
4174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(arg_reg_2);
4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ popq(arg_reg_1);
4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CreateArrayDispatch(MacroAssembler* masm,
4183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                AllocationSiteOverrideMode mode) {
4184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == DISABLE_ALLOCATION_SITES) {
4185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
4186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TailCallStub(&stub);
4187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (mode == DONT_OVERRIDE) {
4188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int last_index = GetSequenceIndexFromFastElementsKind(
4189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TERMINAL_FAST_ELEMENTS_KIND);
4190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i <= last_index; ++i) {
4191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label next;
4192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmpl(rdx, Immediate(kind));
4194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_equal, &next);
4195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      T stub(masm->isolate(), kind);
4196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ TailCallStub(&stub);
4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&next);
4198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we reached this point there is a problem.
4201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Abort(kUnexpectedElementsKindInArrayConstructor);
4202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm,
4209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           AllocationSiteOverrideMode mode) {
4210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rbx - allocation site (if mode != DISABLE_ALLOCATION_SITES)
4211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdx - kind (if mode != DISABLE_ALLOCATION_SITES)
4212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rax - number of arguments
4213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rdi - constructor?
4214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[0] - return address
4215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // rsp[8] - last argument
4216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> undefined_sentinel(
4217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm->isolate()->heap()->undefined_value(),
4218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      masm->isolate());
4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label normal_sequence;
4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == DONT_OVERRIDE) {
4222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(FAST_SMI_ELEMENTS == 0);
4223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(FAST_HOLEY_SMI_ELEMENTS == 1);
4224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(FAST_ELEMENTS == 2);
4225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(FAST_HOLEY_ELEMENTS == 3);
4226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(FAST_DOUBLE_ELEMENTS == 4);
4227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
4228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // is the low bit set? If so, we are holey and that is good.
4230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testb(rdx, Immediate(1));
4231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &normal_sequence);
4232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // look at the first argument
4235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
4236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, args.GetArgumentOperand(0));
4237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rcx, rcx);
4238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(zero, &normal_sequence);
4239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == DISABLE_ALLOCATION_SITES) {
4241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementsKind initial = GetInitialFastElementsKind();
4242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementsKind holey_initial = GetHoleyElementsKind(initial);
4243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArraySingleArgumentConstructorStub stub_holey(masm->isolate(),
4245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  holey_initial,
4246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                  DISABLE_ALLOCATION_SITES);
4247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TailCallStub(&stub_holey);
4248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&normal_sequence);
4250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ArraySingleArgumentConstructorStub stub(masm->isolate(),
4251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            initial,
4252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            DISABLE_ALLOCATION_SITES);
4253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TailCallStub(&stub);
4254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (mode == DONT_OVERRIDE) {
4255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We are going to create a holey array, but our kind is non-holey.
4256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fix kind and retry (only if we have an allocation site in the slot).
4257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ incl(rdx);
4258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_debug_code) {
4260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Handle<Map> allocation_site_map =
4261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          masm->isolate()->factory()->allocation_site_map();
4262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Cmp(FieldOperand(rbx, 0), allocation_site_map);
4263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Assert(equal, kExpectedAllocationSite);
4264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Save the resulting elements kind in type info. We can't just store r3
4267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // in the AllocationSite::transition_info field because elements kind is
4268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // restricted to a portion of the field...upper bits need to be left alone.
4269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiAddConstant(FieldOperand(rbx, AllocationSite::kTransitionInfoOffset),
4271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      Smi::FromInt(kFastElementsKindPackedToHoley));
4272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&normal_sequence);
4274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int last_index = GetSequenceIndexFromFastElementsKind(
4275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TERMINAL_FAST_ELEMENTS_KIND);
4276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i <= last_index; ++i) {
4277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Label next;
4278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ cmpl(rdx, Immediate(kind));
4280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ j(not_equal, &next);
4281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
4282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ TailCallStub(&stub);
4283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ bind(&next);
4284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // If we reached this point there is a problem.
4287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Abort(kUnexpectedElementsKindInArrayConstructor);
4288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
4290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T>
4295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
4296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int to_index = GetSequenceIndexFromFastElementsKind(
4297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TERMINAL_FAST_ELEMENTS_KIND);
4298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i <= to_index; ++i) {
4299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    T stub(isolate, kind);
4301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stub.GetCode();
4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      T stub1(isolate, kind, DISABLE_ALLOCATION_SITES);
4304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      stub1.GetCode();
4305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
4306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
4311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
4312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate);
4313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
4314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate);
4315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
4316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate);
4317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate) {
4322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
4323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < 2; i++) {
4324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // For internal arrays we only need a few things
4325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]);
4326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stubh1.GetCode();
4327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
4328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stubh2.GetCode();
4329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    stubh3.GetCode();
4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayConstructorStub::GenerateDispatchToArrayStub(
4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm,
4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSiteOverrideMode mode) {
4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (argument_count() == ANY) {
4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label not_zero_case, not_one_case;
4340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testp(rax, rax);
4341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(not_zero, &not_zero_case);
4342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&not_zero_case);
4345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpl(rax, Immediate(1));
4346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(greater, &not_one_case);
4347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateArrayDispatchOneArgument(masm, mode);
4348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&not_one_case);
4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (argument_count() == NONE) {
4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (argument_count() == ONE) {
4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateArrayDispatchOneArgument(masm, mode);
4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else if (argument_count() == MORE_THAN_ONE) {
4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ArrayConstructorStub::Generate(MacroAssembler* masm) {
4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------- S t a t e -------------
4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rax    : argc
4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rbx    : AllocationSite or undefined
4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rdi    : constructor
4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0] : return address
4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[8] : last argument
4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------
4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The array construct code is only set for the global and natives
4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // builtin Array functions which always have maps.
4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Initial map for the builtin Array function should be a map.
4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Will both indicate a NULL and a Smi.
4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(rcx, MAP_TYPE, rcx);
4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(equal, kUnexpectedInitialMapForArrayFunction);
4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We should either have undefined in rbx or a valid AllocationSite
4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ AssertUndefinedOrAllocationSite(rbx);
4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_info;
4389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the feedback vector is the undefined value call an array constructor
4390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // that doesn't use AllocationSites.
4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
4392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &no_info);
4393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Only look at the lower 16 bits of the transition info.
4395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rdx, FieldOperand(rbx, AllocationSite::kTransitionInfoOffset));
4396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ SmiToInteger32(rdx, rdx);
4397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ andp(rdx, Immediate(AllocationSite::ElementsKindBits::kMask));
4399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
4400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_info);
4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
4403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayConstructorStub::GenerateCase(
4407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm, ElementsKind kind) {
4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label not_zero_case, not_one_case;
4409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label normal_sequence;
4410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ testp(rax, rax);
4412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(not_zero, &not_zero_case);
4413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
4414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallStub(&stub0);
4415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_zero_case);
4417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpl(rax, Immediate(1));
4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(greater, &not_one_case);
4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsFastPackedElementsKind(kind)) {
4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We might need to create a holey array
4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // look at the first argument
4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
4424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, args.GetArgumentOperand(0));
4425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ testp(rcx, rcx);
4426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(zero, &normal_sequence);
4427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InternalArraySingleArgumentConstructorStub
4429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        stub1_holey(isolate(), GetHoleyElementsKind(kind));
4430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ TailCallStub(&stub1_holey);
4431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&normal_sequence);
4434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
4435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallStub(&stub1);
4436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&not_one_case);
4438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
4439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ TailCallStub(&stubN);
4440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
4444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------- S t a t e -------------
4445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rax    : argc
4446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rdi    : constructor
4447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0] : return address
4448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[8] : last argument
4449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------
4450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The array construct code is only set for the global and natives
4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // builtin Array functions which always have maps.
4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Initial map for the builtin Array function should be a map.
4456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
4457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Will both indicate a NULL and a Smi.
4458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
4459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
4460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(not_smi, kUnexpectedInitialMapForArrayFunction);
4461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CmpObjectType(rcx, MAP_TYPE, rcx);
4462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Check(equal, kUnexpectedInitialMapForArrayFunction);
4463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Figure out the right elements kind
4466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Load the map's "bit field 2" into |result|. We only need the first byte,
4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // but the following masking takes care of that anyway.
4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movzxbp(rcx, FieldOperand(rcx, Map::kBitField2Offset));
4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Retrieve elements_kind from bit field 2.
4472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ DecodeField<Map::ElementsKindBits>(rcx);
4473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
4475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label done;
4476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpl(rcx, Immediate(FAST_ELEMENTS));
4477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ j(equal, &done);
4478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmpl(rcx, Immediate(FAST_HOLEY_ELEMENTS));
4479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(equal,
4480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              kInvalidElementsKindForInternalArrayOrInternalPackedArray);
4481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&done);
4482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label fast_elements_case;
4485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmpl(rcx, Immediate(FAST_ELEMENTS));
4486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &fast_elements_case);
4487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateCase(masm, FAST_HOLEY_ELEMENTS);
4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&fast_elements_case);
4490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  GenerateCase(masm, FAST_ELEMENTS);
4491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallApiFunctionStub::Generate(MacroAssembler* masm) {
4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------- S t a t e -------------
4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rax                 : callee
4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rbx                 : call_data
4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rcx                 : holder
4499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rdx                 : api_function_address
4500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsi                 : context
4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  --
4502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0]              : return address
4503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[8]              : last argument
4504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- ...
4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[argc * 8]       : first argument
4506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[(argc + 1) * 8] : receiver
4507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------
4508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register callee = rax;
4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register call_data = rbx;
4511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register holder = rcx;
4512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register api_function_address = rdx;
4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register return_address = rdi;
4514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register context = rsi;
4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int argc = this->argc();
4517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_store = this->is_store();
4518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool call_data_undefined = this->call_data_undefined();
4519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef FunctionCallbackArguments FCA;
4521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kContextSaveIndex == 6);
4523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kCalleeIndex == 5);
4524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kDataIndex == 4);
4525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
4526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
4527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kIsolateIndex == 1);
4528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kHolderIndex == 0);
4529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(FCA::kArgsLength == 7);
4530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PopReturnAddressTo(return_address);
4532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // context save
4534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(context);
4535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // load context from callee
4536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(context, FieldOperand(callee, JSFunction::kContextOffset));
4537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // callee
4539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(callee);
4540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // call data
4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(call_data);
4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = call_data;
4544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!call_data_undefined) {
4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
4546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // return value
4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(scratch);
4549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // return value default
4550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(scratch);
4551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // isolate
4552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Move(scratch,
4553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ExternalReference::isolate_address(isolate()));
4554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(scratch);
4555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // holder
4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(holder);
4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(scratch, rsp);
4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push return address back on stack.
4560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PushReturnAddressFrom(return_address);
4561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate the v8::Arguments structure in the arguments' space since
4563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // it's not controlled by GC.
4564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kApiStackSpace = 4;
4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PrepareCallApiFunction(kApiStackSpace);
4567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FunctionCallbackInfo::implicit_args_.
4569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(StackSpaceOperand(0), scratch);
4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ addp(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize));
4571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(StackSpaceOperand(1), scratch);  // FunctionCallbackInfo::values_.
4572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(StackSpaceOperand(2), argc);  // FunctionCallbackInfo::length_.
4573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // FunctionCallbackInfo::is_construct_call_.
4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Set(StackSpaceOperand(3), 0);
4575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__MINGW64__) || defined(_WIN64)
4577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register arguments_arg = rcx;
4578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register callback_arg = rdx;
4579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
4580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register arguments_arg = rdi;
4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register callback_arg = rsi;
4582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // It's okay if api_function_address == callback_arg
4585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // but not arguments_arg
4586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!api_function_address.is(arguments_arg));
4587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // v8::InvocationCallback's argument.
4589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(arguments_arg, StackSpaceOperand(0));
4590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference thunk_ref =
4592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::invoke_function_callback(isolate());
4593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Accessor for FunctionCallbackInfo and first js arg.
4595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1,
4596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       ARGUMENTS_DONT_CONTAIN_RECEIVER);
4597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
4598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      FCA::kArgsLength - FCA::kContextSaveIndex);
4599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Stores return the first js argument
4600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand return_value_operand = args_from_rbp.GetArgumentOperand(
4601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      is_store ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset);
4602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallApiFunctionAndReturn(
4603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      api_function_address,
4604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      thunk_ref,
4605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      callback_arg,
4606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      argc + FCA::kArgsLength + 1,
4607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return_value_operand,
4608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      &context_restore_operand);
4609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CallApiGetterStub::Generate(MacroAssembler* masm) {
4613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // ----------- S t a t e -------------
4614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[0]                  : return address
4615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[8]                  : name
4616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- rsp[16 - kArgsLength*8] : PropertyCallbackArguments object
4617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- ...
4618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  -- r8                    : api_function_address
4619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------
4620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__MINGW64__) || defined(_WIN64)
4622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register getter_arg = r8;
4623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register accessor_info_arg = rdx;
4624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register name_arg = rcx;
4625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
4626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register getter_arg = rdx;
4627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register accessor_info_arg = rsi;
4628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register name_arg = rdi;
4629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register api_function_address = ApiGetterDescriptor::function_address();
4631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(api_function_address.is(r8));
4632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = rax;
4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // v8::Arguments::values_ and handler for name.
4635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1;
4636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Allocate v8::AccessorInfo in non-GCed stack space.
4638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int kArgStackSpace = 1;
4639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(name_arg, Operand(rsp, kPCOnStackSize));
4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ PrepareCallApiFunction(kArgStackSpace);
4643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(scratch, Operand(name_arg, 1 * kPointerSize));
4644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // v8::PropertyAccessorInfo::args_.
4646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ movp(StackSpaceOperand(0), scratch);
4647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The context register (rsi) has been saved in PrepareCallApiFunction and
4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // could be used to pass arguments.
4650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ leap(accessor_info_arg, StackSpaceOperand(0));
4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference thunk_ref =
4653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ExternalReference::invoke_accessor_getter_callback(isolate());
4654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // It's okay if api_function_address == getter_arg
4656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // but not accessor_info_arg or name_arg
4657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!api_function_address.is(accessor_info_arg) &&
4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         !api_function_address.is(name_arg));
4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The name handler is counted as an argument.
4661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength);
4662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operand return_value_operand = args.GetArgumentOperand(
4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PropertyCallbackArguments::kArgsLength - 1 -
4664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PropertyCallbackArguments::kReturnValueOffset);
4665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallApiFunctionAndReturn(api_function_address,
4666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              thunk_ref,
4667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              getter_arg,
4668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              kStackSpace,
4669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              return_value_operand,
4670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              NULL);
4671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
4672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
467480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#undef __
467580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
467680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} }  // namespace v8::internal
467780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
467880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#endif  // V8_TARGET_ARCH_X64
4679