1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
73b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/code-stubs.h"
83b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/api-arguments.h"
9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/base/bits.h"
10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/bootstrapper.h"
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/codegen.h"
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/handler-compiler.h"
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/ic/ic.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ic/stub-cache.h"
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/isolate.h"
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ppc/code-stubs-ppc.h"
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/jsregexp.h"
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/regexp-macro-assembler.h"
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define __ ACCESS_MASM(masm)
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
2713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
2813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ StorePX(r4, MemOperand(sp, r0));
2913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ push(r4);
3013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ push(r5);
3113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ addi(r3, r3, Operand(3));
3213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ TailCallRuntime(Runtime::kNewArray);
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
36109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                          Condition cond);
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs,
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Register rhs, Label* lhs_not_nan,
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Label* slow, bool strict);
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs,
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                           Register rhs);
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                               ExternalReference miss) {
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Update the static counter each time a new code stub is generated.
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  isolate()->counters()->code_stubs()->Increment();
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor();
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int param_count = descriptor.GetRegisterParameterCount();
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Call the runtime system in a fresh internal frame.
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(param_count == 0 ||
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           r3.is(descriptor.GetRegisterParameter(param_count - 1)));
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Push arguments
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    for (int i = 0; i < param_count; ++i) {
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ push(descriptor.GetRegisterParameter(i));
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CallExternalReference(miss, param_count);
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DoubleToIStub::Generate(MacroAssembler* masm) {
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label out_of_range, only_low, negate, done, fastpath_done;
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register input_reg = source();
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register result_reg = destination();
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(is_truncating());
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int double_offset = offset();
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Immediate values for this stub fit in instructions, so it's safe to use ip.
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg);
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register scratch_low =
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register scratch_high =
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low);
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DoubleRegister double_scratch = kScratchDoubleReg;
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(scratch);
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Account for saved regs if input is sp.
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (input_reg.is(sp)) double_offset += kPointerSize;
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!skip_fastpath()) {
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Load double input.
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ lfd(double_scratch, MemOperand(input_reg, double_offset));
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Do fast-path convert from double to int.
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ ConvertDoubleToInt64(double_scratch,
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if !V8_TARGET_ARCH_PPC64
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            scratch,
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            result_reg, d0);
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Test for overflow
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ TestIfInt32(result_reg, r0);
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#else
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ TestIfInt32(scratch, result_reg, r0);
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&fastpath_done);
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(scratch_high, scratch_low);
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Account for saved regs if input is sp.
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (input_reg.is(sp)) double_offset += 2 * kPointerSize;
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lwz(scratch_high,
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         MemOperand(input_reg, double_offset + Register::kExponentOffset));
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lwz(scratch_low,
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         MemOperand(input_reg, double_offset + Register::kMantissaOffset));
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ExtractBitMask(scratch, scratch_high, HeapNumber::kExponentMask);
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load scratch with exponent - 1. This is faster than loading
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // with exponent because Bias + 1 = 1024 which is a *PPC* immediate value.
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024);
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ subi(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If exponent is greater than or equal to 84, the 32 less significant
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the result is 0.
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare exponent with 84 (compare exponent - 1 with 83).
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(scratch, Operand(83));
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bge(&out_of_range);
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If we reach this code, 31 <= exponent <= 83.
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // So, we don't have to handle cases where 0 <= exponent <= 20 for
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // which we would need to shift right the high part of the mantissa.
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Scratch contains exponent - 1.
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load scratch with 52 - exponent (load with 51 - (exponent - 1)).
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ subfic(scratch, scratch, Operand(51));
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(scratch, Operand::Zero());
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ble(&only_low);
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 21 <= exponent <= 51, shift scratch_low and scratch_high
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to generate the result.
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ srw(scratch_low, scratch_low, scratch);
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Scratch contains: 52 - exponent.
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // We needs: exponent - 20.
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20.
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ subfic(scratch, scratch, Operand(32));
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ExtractBitMask(result_reg, scratch_high, HeapNumber::kMantissaMask);
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Set the implicit 1 before the mantissa part in scratch_high.
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord >= 16);
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ oris(result_reg, result_reg,
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Operand(1 << ((HeapNumber::kMantissaBitsInTopWord) - 16)));
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ slw(r0, result_reg, scratch);
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ orx(result_reg, scratch_low, r0);
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&negate);
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&out_of_range);
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(result_reg, Operand::Zero());
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&done);
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&only_low);
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 52 <= exponent <= 83, shift only scratch_low.
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // On entry, scratch contains: 52 - exponent.
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ neg(scratch, scratch);
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ slw(result_reg, scratch_low, scratch);
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&negate);
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If input was positive, scratch_high ASR 31 equals 0 and
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // scratch_high LSR 31 equals zero.
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // New result = (result eor 0) + 0 = result.
166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If the input was negative, we have to negate the result.
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1.
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // New result = (result eor 0xffffffff) + 1 = 0 - result.
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ srawi(r0, scratch_high, 31);
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_TARGET_ARCH_PPC64
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ srdi(r0, r0, Operand(32));
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ xor_(result_reg, result_reg, r0);
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ srwi(r0, scratch_high, Operand(31));
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(result_reg, result_reg, r0);
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&done);
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Pop(scratch_high, scratch_low);
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&fastpath_done);
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ pop(scratch);
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Handle the case where the lhs and rhs are the same object.
188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Equality is almost reflexive (everything but NaN), so this is a test
189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// for "identity and not NaN".
190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
191109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                          Condition cond) {
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label not_identical;
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label heap_number, return_equal;
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(r3, r4);
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&not_identical);
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // so we do the second best thing - test it ourselves.
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // They are both equal and they are not both Smis so both of them are not
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Smis.  If it's not a heap number, then return equal.
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (cond == lt || cond == gt) {
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Call runtime on identical JSObjects.
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE);
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bge(slow);
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Call runtime on identical symbols since we need to throw a TypeError.
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmpi(r7, Operand(SYMBOL_TYPE));
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ beq(slow);
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE);
210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&heap_number);
211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Comparing JS objects with <=, >= is complicated.
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (cond != eq) {
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ cmpi(r7, Operand(FIRST_JS_RECEIVER_TYPE));
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ bge(slow);
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Call runtime on identical symbols since we need to throw a TypeError.
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ cmpi(r7, Operand(SYMBOL_TYPE));
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ beq(slow);
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Normally here we fall through to return_equal, but undefined is
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // special: (undefined == undefined) == true, but
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // (undefined <= undefined) == false!  See ECMAScript 11.8.5.
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (cond == le || cond == ge) {
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ cmpi(r7, Operand(ODDBALL_TYPE));
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ bne(&return_equal);
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ cmp(r3, r5);
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ bne(&return_equal);
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (cond == le) {
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          // undefined <= undefined should fail.
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          __ li(r3, Operand(GREATER));
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          // undefined >= undefined should fail.
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          __ li(r3, Operand(LESS));
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        __ Ret();
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&return_equal);
240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (cond == lt) {
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ li(r3, Operand(GREATER));  // Things aren't less than themselves.
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (cond == gt) {
243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ li(r3, Operand(LESS));  // Things aren't greater than themselves.
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ li(r3, Operand(EQUAL));  // Things are <=, >=, ==, === themselves.
246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // For less and greater we don't have to check for NaN since the result of
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // x < x is false regardless.  For the others here is some code to check
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // for NaN.
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (cond != lt && cond != gt) {
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&heap_number);
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // It is a heap number, so return non-equal if it's NaN and equal if it's
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // not NaN.
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // The representation of NaN values has all exponent bits (52..62) set,
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // and not all mantissa bits (0..51) clear.
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Read top bits of double representation (second word of value).
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset));
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Test that exponent bits are all set.
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u);
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ ExtractBitMask(r6, r5, HeapNumber::kExponentMask);
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmpli(r6, Operand(0x7ff));
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bne(&return_equal);
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Shift out flag and all exponent bits, retaining only mantissa.
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord));
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Or with all low-bits of mantissa.
270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ orx(r3, r6, r5);
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmpi(r3, Operand::Zero());
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // For equal we already have the right value in r3:  Return zero (equal)
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // if all bits in mantissa are zero (it's an Infinity) and non-zero if
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // not (it's a NaN).  For <= and >= we need to load r0 with the failing
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // value if it's a NaN.
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (cond != eq) {
278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (CpuFeatures::IsSupported(ISELECT)) {
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ li(r4, Operand((cond == le) ? GREATER : LESS));
280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ isel(eq, r3, r3, r4);
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // All-zero means Infinity means equal.
283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        __ Ret(eq);
284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (cond == le) {
285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ li(r3, Operand(GREATER));  // NaN <= NaN should fail.
286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else {
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          __ li(r3, Operand(LESS));  // NaN >= NaN should fail.
288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        }
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Ret();
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // No fall through here.
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_identical);
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site.
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs,
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Register rhs, Label* lhs_not_nan,
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Label* slow, bool strict) {
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3)));
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label rhs_is_smi;
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(rhs, &rhs_is_smi);
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Lhs is a Smi.  Check whether the rhs is a heap number.
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE);
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (strict) {
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If rhs is not a number and lhs is a Smi then strict equality cannot
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // succeed.  Return non-equal
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If rhs is r3 then there is already a non zero value in it.
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!rhs.is(r3)) {
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Label skip;
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ beq(&skip);
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ mov(r3, Operand(NOT_EQUAL));
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Ret();
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ bind(&skip);
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Ret(ne);
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Smi compared non-strictly with a non-Smi non-heap-number.  Call
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // the runtime.
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bne(slow);
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Lhs is a smi, rhs is a number.
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Convert lhs to a double in d7.
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiToDouble(d7, lhs);
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the double from rhs, tagged HeapNumber r3, to d6.
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // We now have both loaded as doubles but we can skip the lhs nan check
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // since it's a smi.
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(lhs_not_nan);
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&rhs_is_smi);
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rhs is a smi.  Check whether the non-smi lhs is a heap number.
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE);
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (strict) {
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If lhs is not a number and rhs is a smi then strict equality cannot
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // succeed.  Return non-equal.
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If lhs is r3 then there is already a non zero value in it.
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (!lhs.is(r3)) {
347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Label skip;
348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ beq(&skip);
349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ mov(r3, Operand(NOT_EQUAL));
350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Ret();
351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ bind(&skip);
352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ Ret(ne);
354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Smi compared non-strictly with a non-smi non-heap-number.  Call
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // the runtime.
358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bne(slow);
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Rhs is a smi, lhs is a heap number.
362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the double from lhs, tagged HeapNumber r4, to d7.
363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Convert rhs to a double in d6.
365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiToDouble(d6, rhs);
366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Fall through to both_loaded_as_doubles.
367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site.
371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs,
372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                           Register rhs) {
373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3)));
374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If either operand is a JS object or an oddball value, then they are
376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // not equal since their pointers are different.
377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // There is no test for undetectability in strict equality.
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label first_non_object;
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get the type of the first operand into r5 and compare it with
381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // FIRST_JS_RECEIVER_TYPE.
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(rhs, r5, r5, FIRST_JS_RECEIVER_TYPE);
383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blt(&first_non_object);
384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return non-zero (r3 is not zero)
386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label return_not_equal;
387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&return_not_equal);
388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&first_non_object);
391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check for oddballs: true, false, null, undefined.
392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(r5, Operand(ODDBALL_TYPE));
393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&return_not_equal);
394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(lhs, r6, r6, FIRST_JS_RECEIVER_TYPE);
396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bge(&return_not_equal);
397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check for oddballs: true, false, null, undefined.
399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(r6, Operand(ODDBALL_TYPE));
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&return_not_equal);
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Now that we have the types we might as well check for
403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // internalized-internalized.
404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ orx(r5, r5, r6);
406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, r5, Operand(kIsNotStringMask | kIsNotInternalizedMask));
407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&return_not_equal, cr0);
408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// See comment at call site.
412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, Register lhs,
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       Register rhs,
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       Label* both_loaded_as_doubles,
415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       Label* not_heap_numbers, Label* slow) {
416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3)));
417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CompareObjectType(rhs, r6, r5, HEAP_NUMBER_TYPE);
419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(not_heap_numbers);
420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset));
421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(r5, r6);
422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(slow);  // First was a heap number, second wasn't.  Go slow case.
423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Both are heap numbers.  Load them up then jump to the code we have
425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // for that.
426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(both_loaded_as_doubles);
430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
4323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Fast negative check for internalized-to-internalized equality or receiver
4333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// equality. Also handles the undetectable receiver to null/undefined
4343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// comparison.
435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                     Register lhs, Register rhs,
437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                     Label* possible_strings,
438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                                     Label* runtime_call) {
439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3)));
440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r5 is object type of rhs.
4423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Label object_test, return_equal, return_unequal, undetectable;
443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, r5, Operand(kIsNotStringMask));
445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&object_test, cr0);
446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, r5, Operand(kIsNotInternalizedMask));
447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(possible_strings, cr0);
448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CompareObjectType(lhs, r6, r6, FIRST_NONSTRING_TYPE);
449109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bge(runtime_call);
450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, r6, Operand(kIsNotInternalizedMask));
451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(possible_strings, cr0);
452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Both are internalized. We already checked they weren't the same pointer so
454109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // they are not equal. Return non-equal by returning the non-zero object
455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // pointer in r3.
456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&object_test);
459109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset));
460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r6, FieldMemOperand(rhs, HeapObject::kMapOffset));
461109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ lbz(r7, FieldMemOperand(r5, Map::kBitFieldOffset));
462109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ lbz(r8, FieldMemOperand(r6, Map::kBitFieldOffset));
463109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ andi(r0, r7, Operand(1 << Map::kIsUndetectable));
464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bne(&undetectable, cr0);
465109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ andi(r0, r8, Operand(1 << Map::kIsUndetectable));
466109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bne(&return_unequal, cr0);
467109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
468109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareInstanceType(r5, r5, FIRST_JS_RECEIVER_TYPE);
469109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ blt(runtime_call);
470109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareInstanceType(r6, r6, FIRST_JS_RECEIVER_TYPE);
471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ blt(runtime_call);
472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&return_unequal);
474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Return non-equal by returning the non-zero object pointer in r3.
475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Ret();
476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
477109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&undetectable);
478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ andi(r0, r8, Operand(1 << Map::kIsUndetectable));
479109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ beq(&return_unequal, cr0);
4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If both sides are JSReceivers, then the result is false according to
4823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the HTML specification, which says that only comparisons with null or
4833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // undefined are affected by special casing for document.all.
4843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ CompareInstanceType(r5, r5, ODDBALL_TYPE);
4853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ beq(&return_equal);
4863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ CompareInstanceType(r6, r6, ODDBALL_TYPE);
4873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bne(&return_unequal);
4883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
4893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ bind(&return_equal);
490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ li(r3, Operand(EQUAL));
491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void CompareICStub_CheckInputType(MacroAssembler* masm, Register input,
496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                         Register scratch,
497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                         CompareICState::State expected,
498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                         Label* fail) {
499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label ok;
500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (expected == CompareICState::SMI) {
501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfNotSmi(input, fail);
502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (expected == CompareICState::NUMBER) {
503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfSmi(input, &ok);
504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                DONT_DO_SMI_CHECK);
506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // We could be strict about internalized/non-internalized here, but as long as
508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // hydrogen doesn't care, the stub doesn't have to care either.
509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&ok);
510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On entry r4 and r5 are the values to be compared.
514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// On exit r3 is 0, positive or negative to indicate the result of
515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the comparison.
516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateGeneric(MacroAssembler* masm) {
517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register lhs = r4;
518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register rhs = r3;
519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Condition cc = GetCondition();
520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss;
522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CompareICStub_CheckInputType(masm, lhs, r5, left(), &miss);
523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CompareICStub_CheckInputType(masm, rhs, r6, right(), &miss);
524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label slow;  // Call builtin.
526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label not_smis, both_loaded_as_doubles, lhs_not_nan;
527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label not_two_smis, smi_done;
529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ orx(r5, r4, r3);
530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotSmi(r5, &not_two_smis);
531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(r4);
532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(r3);
533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ sub(r3, r4, r3);
534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_two_smis);
536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // NOTICE! This code is only reached after a smi-fast-case check, so
538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // it is certain that at least one operand isn't a smi.
539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Handle the case where the objects are identical.  Either returns the answer
541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // or goes to slow.  Only falls through if the objects were not identical.
542109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  EmitIdenticalObjectComparison(masm, &slow, cc);
543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If either is a Smi (we know that not both are), then they can only
545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // be strictly equal if the other is a HeapNumber.
546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kSmiTag == 0);
547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK_EQ(static_cast<Smi*>(0), Smi::kZero);
548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ and_(r5, lhs, rhs);
549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotSmi(r5, &not_smis);
550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // One operand is a smi.  EmitSmiNonsmiComparison generates code that can:
551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 1) Return the answer.
552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 2) Go to slow.
553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 3) Fall through to both_loaded_as_doubles.
554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // 4) Jump to lhs_not_nan.
555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // In cases 3 and 4 we have found out we were dealing with a number-number
556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // comparison.  The double values of the numbers have been loaded
557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // into d7 and d6.
558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict());
559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&both_loaded_as_doubles);
561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The arguments have been converted to doubles and stored in d6 and d7
562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&lhs_not_nan);
563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label no_nan;
564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ fcmpu(d7, d6);
565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label nan, equal, less_than;
567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bunordered(&nan);
568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(ISELECT)) {
569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(EQUAL == 0);
570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r4, Operand(GREATER));
571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r5, Operand(LESS));
572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(eq, r3, r0, r4);
573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(lt, r3, r5, r3);
574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ beq(&equal);
577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ blt(&less_than);
578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r3, Operand(GREATER));
579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&equal);
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r3, Operand(EQUAL));
582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&less_than);
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r3, Operand(LESS));
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&nan);
589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If one of the sides was a NaN then the v flag is set.  Load r3 with
590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // whatever it takes to make the comparison fail, since comparisons with NaN
591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // always fail.
592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (cc == lt || cc == le) {
593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ li(r3, Operand(GREATER));
594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ li(r3, Operand(LESS));
596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_smis);
600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // At this point we know we are dealing with two different objects,
601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // and neither of them is a Smi.  The objects are in rhs_ and lhs_.
602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (strict()) {
603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // This returns non-equal for some object types, or falls through if it
604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // was not lucky.
605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label check_for_internalized_strings;
609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label flat_string_check;
610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check for heap-number-heap-number comparison.  Can jump to slow case,
611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // or load both doubles into r3, r4, r5, r6 and jump to the code that handles
612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // that case.  If the inputs are not doubles then jumps to
613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // check_for_internalized_strings.
614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // In this case r5 will contain the type of rhs_.  Never falls through.
615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  EmitCheckForTwoHeapNumbers(masm, lhs, rhs, &both_loaded_as_doubles,
616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                             &check_for_internalized_strings,
617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                             &flat_string_check);
618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&check_for_internalized_strings);
620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // internalized strings.
622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (cc == eq && !strict()) {
623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Returns an answer for two internalized strings or two detectable objects.
624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Otherwise jumps to string case or not both strings case.
625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Assumes that r5 is the type of rhs_ on entry.
626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    EmitCheckForInternalizedStringsOrObjects(masm, lhs, rhs, &flat_string_check,
627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                             &slow);
628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check for both being sequential one-byte strings,
631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // and inline if that is the case.
632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&flat_string_check);
633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, r5, r6, &slow);
635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r5,
637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                      r6);
638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (cc == eq) {
639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, r5, r6);
640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r5, r6, r7);
642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Never falls through to here.
644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&slow);
646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (cc == eq) {
648109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    {
649109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
65062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Push(cp);
65162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Call(strict() ? isolate()->builtins()->StrictEqual()
65262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       : isolate()->builtins()->Equal(),
65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              RelocInfo::CODE_TARGET);
65462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Pop(cp);
655109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
656109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Turn true into 0 and false into some non-zero value.
657109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(EQUAL == 0);
658109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadRoot(r4, Heap::kTrueValueRootIndex);
659109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ sub(r3, r3, r4);
660109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Ret();
661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
662109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Push(lhs, rhs);
663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int ncr;  // NaN compare result
664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (cc == lt || cc == le) {
665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ncr = GREATER;
666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(cc == gt || cc == ge);  // remaining cases
668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ncr = LESS;
669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadSmiLiteral(r3, Smi::FromInt(ncr));
671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ push(r3);
672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // tagged as a small integer.
675109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TailCallRuntime(Runtime::kCompare);
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // We don't allow a GC during a store buffer overflow so there is no need to
685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // store the registers in any particular way, but we do have to store and
686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // restore them.
687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mflr(r0);
688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ MultiPush(kJSCallerSaved | r0.bit());
689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (save_doubles()) {
690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ MultiPushDoubles(kCallerSavedDoubles);
691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int argument_count = 1;
693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int fp_argument_count = 0;
694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const Register scratch = r4;
695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AllowExternalCallThatCantCauseGC scope(masm);
697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ PrepareCallCFunction(argument_count, fp_argument_count, scratch);
698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r3, Operand(ExternalReference::isolate_address(isolate())));
699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CallCFunction(ExternalReference::store_buffer_overflow_function(isolate()),
700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   argument_count);
701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (save_doubles()) {
702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ MultiPopDoubles(kCallerSavedDoubles);
703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ MultiPop(kJSCallerSaved | r0.bit());
705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mtlr(r0);
706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreRegistersStateStub::Generate(MacroAssembler* masm) {
711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ PushSafepointRegisters();
712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blr();
713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RestoreRegistersStateStub::Generate(MacroAssembler* masm) {
717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ PopSafepointRegisters();
718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blr();
719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid MathPowStub::Generate(MacroAssembler* masm) {
723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const Register exponent = MathPowTaggedDescriptor::exponent();
724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(exponent.is(r5));
725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const DoubleRegister double_base = d1;
726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const DoubleRegister double_exponent = d2;
727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const DoubleRegister double_result = d3;
728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const DoubleRegister double_scratch = d0;
729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const Register scratch = r11;
730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const Register scratch2 = r10;
731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label call_runtime, done, int_exponent;
733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (exponent_type() == TAGGED) {
734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Base is already in double_base.
735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ lfd(double_exponent,
738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           FieldMemOperand(exponent, HeapNumber::kValueOffset));
739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (exponent_type() != INTEGER) {
742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Detect integer exponents stored as double.
743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ TryDoubleToInt32Exact(scratch, double_exponent, scratch2,
744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                             double_scratch);
745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&int_exponent);
746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mflr(r0);
748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ push(r0);
749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    {
750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      AllowExternalCallThatCantCauseGC scope(masm);
751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ PrepareCallCFunction(0, 2, scratch);
752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ MovToFloatParameters(double_base, double_exponent);
753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ CallCFunction(
754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          ExternalReference::power_double_double_function(isolate()), 0, 2);
755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ pop(r0);
757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mtlr(r0);
758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ MovFromFloatResult(double_result);
759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ b(&done);
760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Calculate power with integer exponent.
763958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&int_exponent);
764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
765958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get two copies of exponent in the registers scratch and exponent.
766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (exponent_type() == INTEGER) {
767958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mr(scratch, exponent);
768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Exponent has previously been stored into scratch as untagged integer.
770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mr(exponent, scratch);
771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ fmr(double_scratch, double_base);  // Back up base.
773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(scratch2, Operand(1));
774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ConvertIntToDouble(scratch2, double_result);
775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get absolute value of exponent.
777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(scratch, Operand::Zero());
778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(ISELECT)) {
779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ neg(scratch2, scratch);
780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(lt, scratch, scratch2, scratch);
781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label positive_exponent;
783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bge(&positive_exponent);
784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ neg(scratch, scratch);
785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&positive_exponent);
786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label while_true, no_carry, loop_end;
789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&while_true);
790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(scratch2, scratch, Operand(1));
791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&no_carry, cr0);
792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ fmul(double_result, double_result, double_scratch);
793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&no_carry);
794f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ ShiftRightImm(scratch, scratch, Operand(1), SetRC);
795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&loop_end, cr0);
796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ fmul(double_scratch, double_scratch, double_scratch);
797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&while_true);
798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&loop_end);
799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(exponent, Operand::Zero());
801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bge(&done);
802958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
803958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(scratch2, Operand(1));
804958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ConvertIntToDouble(scratch2, double_scratch);
805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ fdiv(double_result, double_scratch, double_result);
806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Test whether result is zero.  Bail out to check for subnormal result.
807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ fcmpu(double_result, kDoubleRegZero);
809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&done);
810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // double_exponent may not containe the exponent value if the input was a
811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // smi.  We set it with exponent value before bailing out.
812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ConvertIntToDouble(exponent, double_exponent);
813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Returning or bailing out.
815f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ mflr(r0);
816f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ push(r0);
817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    AllowExternalCallThatCantCauseGC scope(masm);
819f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    __ PrepareCallCFunction(0, 2, scratch);
820f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    __ MovToFloatParameters(double_base, double_exponent);
821f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    __ CallCFunction(
822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        ExternalReference::power_double_double_function(isolate()), 0, 2);
823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
824f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ pop(r0);
825f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ mtlr(r0);
826f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ MovFromFloatResult(double_result);
827f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
828f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ bind(&done);
829f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Ret();
830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool CEntryStub::NeedsImmovableCode() { return true; }
834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CEntryStub::GenerateAheadOfTime(isolate);
838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
84013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CreateWeakCellStub::GenerateAheadOfTime(isolate);
843958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  BinaryOpICStub::GenerateAheadOfTime(isolate);
844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StoreRegistersStateStub::GenerateAheadOfTime(isolate);
845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RestoreRegistersStateStub::GenerateAheadOfTime(isolate);
846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StoreFastElementStub::GenerateAheadOfTime(isolate);
848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) {
852958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StoreRegistersStateStub stub(isolate);
853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  stub.GetCode();
854958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
855958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
856958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
857958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) {
858958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RestoreRegistersStateStub stub(isolate);
859958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  stub.GetCode();
860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
863958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CodeStub::GenerateFPStubs(Isolate* isolate) {
864958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Generate if not already in cache.
865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  SaveFPRegsMode mode = kSaveFPRegs;
866958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CEntryStub(isolate, 1, mode).GetCode();
867958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StoreBufferOverflowStub(isolate, mode).GetCode();
868958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CEntryStub stub(isolate, 1, kDontSaveFPRegs);
873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  stub.GetCode();
874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CEntryStub::Generate(MacroAssembler* masm) {
878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Called from JavaScript; parameters are on stack as if calling JS function.
879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3: number of arguments including receiver
880958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: pointer to builtin function
881958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // fp: frame pointer  (restored after C call)
882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // sp: stack pointer  (restored as callee's sp after C call)
883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // cp: current context  (C callee-saved)
884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If argv_in_register():
886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r5: pointer to the first argument
887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ProfileEntryHookStub::MaybeCallEntryHook(masm);
888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r15, r4);
890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (argv_in_register()) {
892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Move argv into the correct register.
893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mr(r4, r5);
894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Compute the argv pointer.
896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2));
897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ add(r4, r4, sp);
898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ subi(r4, r4, Operand(kPointerSize));
899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Enter the exit frame that transitions from JavaScript to C++.
902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FrameScope scope(masm, StackFrame::MANUAL);
903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Need at least one extra slot for return address location.
905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int arg_stack_space = 1;
906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Pass buffer for return value on stack if necessary
908109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool needs_return_buffer =
909109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      result_size() > 2 ||
910109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      (result_size() == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS);
911109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (needs_return_buffer) {
912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    arg_stack_space += result_size();
913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
915f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ EnterExitFrame(save_doubles(), arg_stack_space, is_builtin_exit()
916f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                           ? StackFrame::BUILTIN_EXIT
917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                           : StackFrame::EXIT);
918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Store a copy of argc in callee-saved registers for later.
920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r14, r3);
921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3, r14: number of arguments including receiver  (C callee-saved)
923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: pointer to the first argument
924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r15: pointer to builtin function  (C callee-saved)
925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Result returned in registers or stack, depending on result size and ABI.
927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register isolate_reg = r5;
929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (needs_return_buffer) {
930109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // The return value is a non-scalar value.
931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Use frame storage reserved by calling function to pass return
932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // buffer as implicit first argument.
933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mr(r5, r4);
934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mr(r4, r3);
935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    isolate_reg = r6;
937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Call C built-in.
940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate())));
941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register target = r15;
943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (ABI_USES_FUNCTION_DESCRIPTORS) {
944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // AIX/PPC64BE Linux use a function descriptor.
945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
946109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(ip, MemOperand(r15, 0));  // Instruction address
947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    target = ip;
948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else if (ABI_CALL_VIA_IP) {
949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Move(ip, r15);
950109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    target = ip;
951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // To let the GC traverse the return address of the exit frames, we need to
954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // know where the return address is. The CEntryStub is unmovable, so
955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // we can store the address on the stack to be able to find it again and
956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // we never have to restore it, because it will not change.
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label after_call;
958014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov_label_addr(r0, &after_call);
959014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Call(target);
961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&after_call);
962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If return value is on the stack, pop it to registers.
964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (needs_return_buffer) {
965109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (result_size() > 2) __ LoadP(r5, MemOperand(r3, 2 * kPointerSize));
966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(r4, MemOperand(r3, kPointerSize));
967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(r3, MemOperand(r3));
968958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
970958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check result for exception sentinel.
971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label exception_returned;
972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CompareRoot(r3, Heap::kExceptionRootIndex);
973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&exception_returned);
974958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that there is no pending exception, otherwise we
976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // should have returned the exception sentinel.
977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (FLAG_debug_code) {
978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label okay;
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ExternalReference pending_exception_address(
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        Isolate::kPendingExceptionAddress, isolate());
981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ mov(r6, Operand(pending_exception_address));
983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(r6, MemOperand(r6));
984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Cannot use check here as it attempts to generate call into runtime.
986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&okay);
987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ stop("Unexpected pending exception");
988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&okay);
989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Exit C frame and return.
992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3:r4: result
993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // sp: stack pointer
994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // fp: frame pointer
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register argc;
996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (argv_in_register()) {
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // We don't want to pop arguments so set argc to no_reg.
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    argc = no_reg;
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // r14: still holds argc (callee-saved).
1001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    argc = r14;
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LeaveExitFrame(save_doubles(), argc, true);
1004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blr();
1005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Handling of exception.
1007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&exception_returned);
1008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference pending_handler_context_address(
1010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate::kPendingHandlerContextAddress, isolate());
1011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference pending_handler_code_address(
1012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate::kPendingHandlerCodeAddress, isolate());
1013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference pending_handler_offset_address(
1014014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate::kPendingHandlerOffsetAddress, isolate());
1015014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference pending_handler_fp_address(
1016014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate::kPendingHandlerFPAddress, isolate());
1017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference pending_handler_sp_address(
1018014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Isolate::kPendingHandlerSPAddress, isolate());
1019014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Ask the runtime for help to determine the handler. This will set r3 to
1021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // contain the current pending exception, don't clobber it.
1022014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 isolate());
1024014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope scope(masm, StackFrame::MANUAL);
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ PrepareCallCFunction(3, 0, r3);
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r3, Operand::Zero());
1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r4, Operand::Zero());
1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
1030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallCFunction(find_handler, 3);
1031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Retrieve the handler context, SP and FP.
1034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(cp, Operand(pending_handler_context_address));
1035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(cp, MemOperand(cp));
1036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(sp, Operand(pending_handler_sp_address));
1037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(sp, MemOperand(sp));
1038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(fp, Operand(pending_handler_fp_address));
1039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(fp, MemOperand(fp));
1040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the handler is a JS frame, restore the context to the frame. Note that
1042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the context will be set to (cp == 0) for non-JS frames.
1043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label skip;
1044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmpi(cp, Operand::Zero());
1045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ beq(&skip);
1046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&skip);
1048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compute the handler entry address and jump to it.
1050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ConstantPoolUnavailableScope constant_pool_unavailable(masm);
1051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r4, Operand(pending_handler_code_address));
1052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r4, MemOperand(r4));
1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r5, Operand(pending_handler_offset_address));
1054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r5, MemOperand(r5));
1055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start
1056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r4);
1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ add(ip, r4, r5);
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Jump(ip);
1061958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1062958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1063958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid JSEntryStub::Generate(MacroAssembler* masm) {
1065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3: code entry
1066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: function
1067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r5: receiver
1068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r6: argc
1069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // [sp+0]: argv
1070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label invoke, handler_entry, exit;
1072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Called from C
1074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ function_descriptor();
1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ProfileEntryHookStub::MaybeCallEntryHook(masm);
1077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // PPC LINUX ABI:
1079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // preserve LR in pre-reserved slot in caller's frame
1080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mflr(r0);
1081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
1082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Save callee saved registers on the stack.
1084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ MultiPush(kCalleeSaved);
1085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Save callee-saved double registers.
1087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ MultiPushDoubles(kCalleeSavedDoubles);
1088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Set up the reserved register for 0.0.
1089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadDoubleLiteral(kDoubleRegZero, 0.0, r0);
1090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Push a frame with special values setup to mark it as an entry frame.
1092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3: code entry
1093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: function
1094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r5: receiver
1095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r6: argc
1096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r7: argv
1097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(r0, Operand(-1));  // Push a bad frame pointer to fail if it is used.
1098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(r0);
1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_enable_embedded_constant_pool) {
1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(kConstantPoolRegister, Operand::Zero());
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ push(kConstantPoolRegister);
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
110362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  StackFrame::Type marker = type();
110462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ mov(r0, Operand(StackFrame::TypeToMarker(marker)));
1105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(r0);
1106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(r0);
1107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Save copies of the top frame descriptor on the stack.
1108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r0, MemOperand(r8));
1110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(r0);
1111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Set up frame pointer for the frame to be pushed.
1113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If this is the outermost JS call, set js_entry_sp value.
1116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label non_outermost_js;
1117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate());
1118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r8, Operand(ExternalReference(js_entry_sp)));
1119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r9, MemOperand(r8));
1120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(r9, Operand::Zero());
1121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&non_outermost_js);
1122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(fp, MemOperand(r8));
112362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ mov(ip, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
1124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label cont;
1125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&cont);
1126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&non_outermost_js);
112762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ mov(ip, Operand(StackFrame::INNER_JSENTRY_FRAME));
1128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&cont);
1129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(ip);  // frame-type
1130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Jump to a faked try block that does the invoke, with a faked catch
1132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // block that sets the pending exception.
1133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&invoke);
1134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&handler_entry);
1136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  handler_offset_ = handler_entry.pos();
1137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Caught exception: Store result (exception) in the pending exception
1138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // field in the JSEnv and return a failure sentinel.  Coming in here the
1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // fp will be invalid because the PushStackHandler below sets it to 0 to
1140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // signal the existence of the JSEntry frame.
1141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       isolate())));
1143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(r3, MemOperand(ip));
1145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadRoot(r3, Heap::kExceptionRootIndex);
1146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&exit);
1147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Invoke: Link this frame into the handler chain.
1149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&invoke);
1150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Must preserve r3-r7.
1151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ PushStackHandler();
1152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If an exception not caught by another handler occurs, this handler
1153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // returns control to the code after the b(&invoke) above, which
1154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // restores all kCalleeSaved registers (including cp and fp) to their
1155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // saved values before returning a failure to C.
1156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Invoke the function by calling through JS entry trampoline builtin.
1158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Notice that we cannot store a reference to the trampoline code directly in
1159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // this stub, because runtime stubs are not traversed when doing GC.
1160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Expected registers by Builtins::JSEntryTrampoline
1162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3: code entry
1163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: function
1164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r5: receiver
1165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r6: argc
1166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r7: argv
1167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (type() == StackFrame::ENTRY_CONSTRUCT) {
1168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
1169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                      isolate());
1170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mov(ip, Operand(construct_entry));
1171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
1172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ExternalReference entry(Builtins::kJSEntryTrampoline, isolate());
1173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ mov(ip, Operand(entry));
1174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(ip, MemOperand(ip));  // deref address
1176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Branch and link to JSEntryTrampoline.
1178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the address points to the start of the code object, skip the header
1179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
1180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mtctr(ip);
1181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bctrl();  // make the call
1182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Unlink this frame from the handler chain.
1184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ PopStackHandler();
1185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&exit);  // r3 holds result
1187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if the current stack frame is marked as the outermost JS frame.
1188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label non_outermost_js_2;
1189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ pop(r8);
119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ cmpi(r8, Operand(StackFrame::OUTERMOST_JSENTRY_FRAME));
1191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&non_outermost_js_2);
1192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r9, Operand::Zero());
1193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r8, Operand(ExternalReference(js_entry_sp)));
1194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(r9, MemOperand(r8));
1195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&non_outermost_js_2);
1196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Restore the top frame descriptors from the stack.
1198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ pop(r6);
1199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(r6, MemOperand(ip));
1201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Reset the stack to the callee saved registers.
1203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Restore callee-saved double registers.
1206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ MultiPopDoubles(kCalleeSavedDoubles);
1207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Restore callee-saved registers.
1209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ MultiPop(kCalleeSaved);
1210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Return
1212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
1213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mtlr(r0);
1214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ blr();
1215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1217109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid RegExpExecStub::Generate(MacroAssembler* masm) {
1218109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// Just jump directly to runtime if native RegExp is not selected at compile
1219109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// time or if regexp entry in generated code is turned off runtime switch or
1220109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// at compilation.
1221109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#ifdef V8_INTERPRETED_REGEXP
1222109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ TailCallRuntime(Runtime::kRegExpExec);
1223109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else  // V8_INTERPRETED_REGEXP
1224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1225109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Stack frame on entry.
1226109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  sp[0]: last_match_info (expected JSArray)
1227109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  sp[4]: previous index
1228109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  sp[8]: subject string
1229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  sp[12]: JSRegExp object
1230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1231109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int kLastMatchInfoOffset = 0 * kPointerSize;
1232109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int kPreviousIndexOffset = 1 * kPointerSize;
1233109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int kSubjectOffset = 2 * kPointerSize;
1234109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int kJSRegExpOffset = 3 * kPointerSize;
1235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1236109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label runtime, br_over, encoding_type_UC16;
1237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1238109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Allocation of registers for this function. These are in callee save
1239109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // registers and will be preserved by the call to the native RegExp code, as
1240109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // this code is called using the normal C calling convention. When calling
1241109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // directly from generated code the native RegExp code will not do a GC and
1242109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // therefore the content of these registers are safe to use after the call.
1243109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Register subject = r14;
1244109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Register regexp_data = r15;
1245109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Register last_match_info_elements = r16;
1246109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Register code = r17;
1247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1248109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Ensure register assigments are consistent with callee save masks
1249109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(subject.bit() & kCalleeSaved);
1250109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(regexp_data.bit() & kCalleeSaved);
1251109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(last_match_info_elements.bit() & kCalleeSaved);
1252109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DCHECK(code.bit() & kCalleeSaved);
1253f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
1254109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Ensure that a RegExp stack is allocated.
1255109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ExternalReference address_of_regexp_stack_memory_address =
1256109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      ExternalReference::address_of_regexp_stack_memory_address(isolate());
1257109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ExternalReference address_of_regexp_stack_memory_size =
1258109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      ExternalReference::address_of_regexp_stack_memory_size(isolate());
1259109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mov(r3, Operand(address_of_regexp_stack_memory_size));
1260109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r3, MemOperand(r3, 0));
1261109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ cmpi(r3, Operand::Zero());
1262109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ beq(&runtime);
1263f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
1264109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Check that the first argument is a JSRegExp object.
1265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r3, MemOperand(sp, kJSRegExpOffset));
1266109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ JumpIfSmi(r3, &runtime);
1267109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareObjectType(r3, r4, r4, JS_REGEXP_TYPE);
1268109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bne(&runtime);
1269f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
1270109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Check that the RegExp has been compiled (data contains a fixed array).
1271109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(regexp_data, FieldMemOperand(r3, JSRegExp::kDataOffset));
1272109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
1273109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TestIfSmi(regexp_data, r0);
1274109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected, cr0);
1275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CompareObjectType(regexp_data, r3, r3, FIXED_ARRAY_TYPE);
1276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // regexp_data: RegExp data (FixedArray)
1280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
1281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r3, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
1282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // DCHECK(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu);
1283109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CmpSmiLiteral(r3, Smi::FromInt(JSRegExp::IRREGEXP), r0);
1284109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bne(&runtime);
1285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1286109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // regexp_data: RegExp data (FixedArray)
1287109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Check that the number of captures fit in the static offsets vector buffer.
1288109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r5,
1289109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch           FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1290109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Check (number_of_captures + 1) * 2 <= offsets vector size
1291109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Or          number_of_captures * 2 <= offsets vector size - 2
1292109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // SmiToShortArrayOffset accomplishes the multiplication by 2 and
1293109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // SmiUntag (which is a nop for 32-bit).
1294109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ SmiToShortArrayOffset(r5, r5);
1295109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1296109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ cmpli(r5, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
1297109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bgt(&runtime);
1298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1299109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Reset offset for possibly sliced string.
1300109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ li(r11, Operand::Zero());
1301109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(subject, MemOperand(sp, kSubjectOffset));
1302109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ JumpIfSmi(subject, &runtime);
1303109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mr(r6, subject);  // Make a copy of the original subject string.
1304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // subject: subject string
1305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // r6: subject string
1306109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // regexp_data: RegExp data (FixedArray)
1307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Handle subject string according to its encoding and representation:
1308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (1) Sequential string?  If yes, go to (4).
1309109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (2) Sequential or cons?  If not, go to (5).
1310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (3) Cons string.  If the string is flat, replace subject with first string
1311109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //     and go to (1). Otherwise bail out to runtime.
1312109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (4) Sequential string.  Load regexp code according to encoding.
1313109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (E) Carry on.
1314109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  /// [...]
1315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Deferred code at the end of the stub:
1317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (5) Long external string?  If not, go to (7).
1318109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (6) External string.  Make it, offset-wise, look like a sequential string.
1319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //     Go to (4).
1320109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (7) Short external string or not a string?  If yes, bail out to runtime.
132162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // (8) Sliced or thin string.  Replace subject with parent.  Go to (1).
1322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1323109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label seq_string /* 4 */, external_string /* 6 */, check_underlying /* 1 */,
1324109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      not_seq_nor_cons /* 5 */, not_long_external /* 7 */;
1325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1326109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&check_underlying);
1327109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
1328109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
1329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (1) Sequential string?  If yes, go to (4).
1331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask |
133362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 kShortExternalStringMask) == 0xa7);
1334109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask |
1335109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                          kShortExternalStringMask));
1336109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
1337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ beq(&seq_string, cr0);  // Go to (4).
1338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (2) Sequential or cons? If not, go to (5).
1340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT(kConsStringTag < kExternalStringTag);
1341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
134262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(kThinStringTag > kExternalStringTag);
1343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
1344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1345109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT(kExternalStringTag < 0xffffu);
1346109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ cmpi(r4, Operand(kExternalStringTag));
1347109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bge(&not_seq_nor_cons);  // Go to (5).
1348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1349109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (3) Cons string.  Check that it's flat.
1350109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Replace subject with first string and reload instance type.
1351109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r3, FieldMemOperand(subject, ConsString::kSecondOffset));
1352109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareRoot(r3, Heap::kempty_stringRootIndex);
1353109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bne(&runtime);
1354109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
1355109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ b(&check_underlying);
1356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (4) Sequential string.  Load regexp code according to encoding.
1358f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  __ bind(&seq_string);
1359f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  // subject: sequential subject string (or look-alike, external string)
1360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r6: original subject string
1361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load previous index and check range before r6 is overwritten.  We have to
1362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // use r6 instead of subject here because subject might have been only made
1363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to look like a sequential string when it actually is an external string.
1364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r4, MemOperand(sp, kPreviousIndexOffset));
1365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotSmi(r4, &runtime);
1366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r6, FieldMemOperand(r6, String::kLengthOffset));
1367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpl(r6, r4);
1368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ble(&runtime);
1369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(r4);
1370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
137162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(8 == kOneByteStringTag);
1372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kTwoByteStringTag == 0);
137362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(kStringEncodingMask == 8);
1374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ExtractBitMask(r6, r3, kStringEncodingMask, SetRC);
1375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&encoding_type_UC16, cr0);
1376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(code,
1377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset));
1378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&br_over);
1379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&encoding_type_UC16);
1380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
1381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&br_over);
1382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // (E) Carry on.  String handling is done.
1384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // code: irregexp code
1385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the irregexp code has been generated for the actual string
1386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // encoding. If it has, the field contains a code object otherwise it contains
1387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // a smi (code flushing support).
1388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(code, &runtime);
1389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: previous index
1391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r6: encoding of subject string (1 if one_byte, 0 if two_byte);
1392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // code: Address of generated regexp code
1393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // subject: Subject string
1394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // regexp_data: RegExp data (FixedArray)
1395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // All checks done. Now push arguments for native regexp code.
1396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r3, r5);
1397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Isolates: note we add an additional parameter here (isolate pointer).
1399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int kRegExpExecuteArguments = 10;
1400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int kParameterRegisters = 8;
1401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
1402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Stack pointer now points to cell where return address is to be written.
1404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Arguments are before that on the stack or in registers.
1405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 10 (in stack parameter area): Pass current isolate address.
1407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r3, Operand(ExternalReference::isolate_address(isolate())));
1408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(r3, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize));
1409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 9 is a dummy that reserves the space used for
1411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the return address added by the ExitFrame in native calls.
1412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 8 (r10): Indicate that this is a direct call from JavaScript.
1414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(r10, Operand(1));
1415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 7 (r9): Start (high end) of backtracking stack memory area.
1417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r3, Operand(address_of_regexp_stack_memory_address));
1418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r3, MemOperand(r3, 0));
1419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r5, Operand(address_of_regexp_stack_memory_size));
1420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r5, MemOperand(r5, 0));
1421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(r9, r3, r5);
1422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 6 (r8): Set the number of capture registers to zero to force
1424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // global egexps to behave as non-global.  This does not affect non-global
1425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // regexps.
1426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(r8, Operand::Zero());
1427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 5 (r7): static offsets vector buffer.
1429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(
1430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      r7,
1431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
1432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // For arguments 4 (r6) and 3 (r5) get string length, calculate start of data
1434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // and calculate the shift of the index (0 for one-byte and 1 for two-byte).
1435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(r18, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
1436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ xori(r6, r6, Operand(1));
1437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load the length from the original subject string from the previous stack
1438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // frame. Therefore we have to use fp, which points exactly to two pointer
1439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // sizes below the previous sp. (Because creating a new stack frame pushes
1440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
1441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
1442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If slice offset is not 0, load the length from the original sliced string.
1443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 4, r6: End of string data
1444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 3, r5: Start of string data
1445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Prepare start and end index of the input.
1446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ShiftLeft_(r11, r11, r6);
1447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(r11, r18, r11);
1448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ShiftLeft_(r5, r4, r6);
1449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(r5, r11, r5);
1450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r18, FieldMemOperand(subject, String::kLengthOffset));
1452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(r18);
1453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ShiftLeft_(r6, r18, r6);
1454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(r6, r11, r6);
1455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 2 (r4): Previous index.
1457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Already there
1458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Argument 1 (r3): Subject string.
1460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r3, subject);
1461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Locate the code entry and call it.
1463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(code, code, Operand(Code::kHeaderSize - kHeapObjectTag));
1464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DirectCEntryStub stub(isolate());
1466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  stub.GenerateCall(masm, code);
1467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LeaveExitFrame(false, no_reg, true);
1469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r3: result (int32)
1471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // subject: subject string (callee saved)
1472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // regexp_data: RegExp data (callee saved)
1473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // last_match_info_elements: Last match info elements (callee saved)
1474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check the result.
1475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label success;
1476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmpwi(r3, Operand(1));
1477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // We expect exactly one result since we force the called regexp to behave
1478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // as non-global.
1479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&success);
1480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label failure;
1481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::FAILURE));
1482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&failure);
1483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::EXCEPTION));
1484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If not exception it can only be retry. Handle that in the runtime system.
1485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&runtime);
1486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Result must now be exception. If there is no pending exception already a
1487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // stack overflow (on the backtrack stack) was detected in RegExp code but
1488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // haven't created the exception yet. Handle that in the runtime system.
1489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // TODO(592): Rerunning the RegExp to get the stack overflow exception.
1490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r4, Operand(isolate()->factory()->the_hole_value()));
1491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r5, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       isolate())));
1493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r3, MemOperand(r5, 0));
1494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(r3, r4);
1495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&runtime);
1496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // For exception, throw the exception again.
1498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TailCallRuntime(Runtime::kRegExpExecReThrow);
1499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&failure);
1501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // For failure and exception return null.
1502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r3, Operand(isolate()->factory()->null_value()));
1503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(sp, sp, Operand(4 * kPointerSize));
1504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
1505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Process the result from the native regexp code.
1507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&success);
1508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r4,
1509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Calculate number of capture registers (number_of_captures + 1) * 2.
1511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // SmiToShortArrayOffset accomplishes the multiplication by 2 and
1512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // SmiUntag (which is a nop for 32-bit).
1513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiToShortArrayOffset(r4, r4);
1514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(r4, r4, Operand(2));
1515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Check that the last match info is a FixedArray.
1517c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ LoadP(last_match_info_elements, MemOperand(sp, kLastMatchInfoOffset));
1518c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ JumpIfSmi(last_match_info_elements, &runtime);
1519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check that the object has fast elements.
1520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r3,
1521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
1522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CompareRoot(r3, Heap::kFixedArrayMapRootIndex);
1523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&runtime);
1524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that the last match info has space for the capture registers and the
1525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // additional information.
1526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(
1527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      r3, FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
1528c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ addi(r5, r4, Operand(RegExpMatchInfo::kLastMatchOverhead));
1529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(r0, r3);
1530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(r5, r0);
1531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bgt(&runtime);
1532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: number of capture registers
1534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // subject: subject string
1535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Store the capture count.
1536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiTag(r5, r4);
1537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(r5, FieldMemOperand(last_match_info_elements,
1538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                RegExpMatchInfo::kNumberOfCapturesOffset),
1539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            r0);
1540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Store last subject and last input.
1541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(subject, FieldMemOperand(last_match_info_elements,
1542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                     RegExpMatchInfo::kLastSubjectOffset),
1543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            r0);
1544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r5, subject);
1545c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ RecordWriteField(last_match_info_elements,
1546c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                      RegExpMatchInfo::kLastSubjectOffset, subject, r10,
1547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                      kLRHasNotBeenSaved, kDontSaveFPRegs);
1548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(subject, r5);
1549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(subject, FieldMemOperand(last_match_info_elements,
1550c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                     RegExpMatchInfo::kLastInputOffset),
1551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            r0);
1552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ RecordWriteField(last_match_info_elements,
1553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                      RegExpMatchInfo::kLastInputOffset, subject, r10,
1554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                      kLRHasNotBeenSaved, kDontSaveFPRegs);
1555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get the static offsets vector filled by the native regexp code.
1557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference address_of_static_offsets_vector =
1558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ExternalReference::address_of_static_offsets_vector(isolate());
1559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r5, Operand(address_of_static_offsets_vector));
1560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4: number of capture registers
1562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r5: offsets vector
1563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label next_capture;
1564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Capture register counter starts from number of capture registers and
1565c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // counts down until wrapping after zero.
1566c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ addi(r3, last_match_info_elements,
1567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          Operand(RegExpMatchInfo::kFirstCaptureOffset - kHeapObjectTag -
1568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  kPointerSize));
1569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(r5, r5, Operand(-kIntSize));  // bias down for lwzu
1570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mtctr(r4);
1571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&next_capture);
1572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Read the value from the static offsets vector buffer.
1573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lwzu(r6, MemOperand(r5, kIntSize));
1574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Store the smi value in the last match info.
1575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiTag(r6);
1576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StorePU(r6, MemOperand(r3, kPointerSize));
1577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bdnz(&next_capture);
1578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return last match info.
1580c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ mr(r3, last_match_info_elements);
1581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(sp, sp, Operand(4 * kPointerSize));
1582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
1583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Do the runtime call to execute the regexp.
1585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&runtime);
1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TailCallRuntime(Runtime::kRegExpExec);
1587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Deferred code for string handling.
1589109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (5) Long external string? If not, go to (7).
1590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_seq_nor_cons);
1591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare flags are still set.
1592109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bgt(&not_long_external);  // Go to (7).
1593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1594109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (6) External string.  Make it, offset-wise, look like a sequential string.
1595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&external_string);
1596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
1597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
1598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (FLAG_debug_code) {
1599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Assert that we do not have a cons or slice (indirect strings) here.
1600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Sequential strings have already been ruled out.
1601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    STATIC_ASSERT(kIsIndirectStringMask == 1);
1602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ andi(r0, r3, Operand(kIsIndirectStringMask));
1603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Assert(eq, kExternalStringExpectedButNotFound, cr0);
1604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(subject,
1606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier           FieldMemOperand(subject, ExternalString::kResourceDataOffset));
1607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Move the pointer so that offset-wise, it looks like a sequential string.
1608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ subi(subject, subject,
1610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
1611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ b(&seq_string);  // Go to (4).
1612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1613109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // (7) Short external string or not a string?  If yes, bail out to runtime.
1614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_long_external);
1615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0);
1616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask));
1617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&runtime, cr0);
1618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
161962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // (8) Sliced or thin string.  Replace subject with parent.  Go to (4).
162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label thin_string;
162162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ cmpi(r4, Operand(kThinStringTag));
162262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ beq(&thin_string);
1623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load offset into r11 and replace subject string with parent.
1624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset));
1625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(r11);
1626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
1627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&check_underlying);  // Go to (4).
162862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
162962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ bind(&thin_string);
163062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ LoadP(subject, FieldMemOperand(subject, ThinString::kActualOffset));
163162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ b(&check_underlying);  // Go to (4).
1632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif  // V8_INTERPRETED_REGEXP
1633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
1637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r3 : number of arguments to the construct function
1638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r4 : the function to call
1639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r5 : feedback vector
1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r6 : slot in feedback vector (Smi)
1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Number-of-arguments register must be smi-tagged to call out.
1644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ SmiTag(r3);
1645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Push(r6, r5, r4, r3);
1646f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Push(cp);
1647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1648014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallStub(stub);
1649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1650f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Pop(cp);
1651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Pop(r6, r5, r4, r3);
1652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ SmiUntag(r3);
1653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
1654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void GenerateRecordCallTarget(MacroAssembler* masm) {
1657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Cache the called function in a feedback vector slot.  Cache states
1658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // are uninitialized, monomorphic (indicated by a JSFunction), and
1659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // megamorphic.
1660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3 : number of arguments to the construct function
1661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r4 : the function to call
1662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r5 : feedback vector
1663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r6 : slot in feedback vector (Smi)
1664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label initialize, done, miss, megamorphic, not_array_function;
1665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
166662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(*FeedbackVector::MegamorphicSentinel(masm->isolate()),
1667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            masm->isolate()->heap()->megamorphic_symbol());
166862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(*FeedbackVector::UninitializedSentinel(masm->isolate()),
1669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            masm->isolate()->heap()->uninitialized_symbol());
1670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
167113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  const int count_offset = FixedArray::kHeaderSize + kPointerSize;
167213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Load the cache state into r8.
1674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ SmiToPtrArrayOffset(r8, r6);
1675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ add(r8, r5, r8);
1676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r8, FieldMemOperand(r8, FixedArray::kHeaderSize));
1677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // A monomorphic cache hit or an already megamorphic state: invoke the
1679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // function without changing the state.
1680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // We don't know if r8 is a WeakCell or a Symbol, but it's harmless to read at
168162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // this position in a symbol (see static asserts in feedback-vector.h).
1682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label check_allocation_site;
1683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register feedback_map = r9;
1684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register weak_value = r10;
1685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(weak_value, FieldMemOperand(r8, WeakCell::kValueOffset));
1686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(r4, weak_value);
1687f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ beq(&done);
1688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(r8, Heap::kmegamorphic_symbolRootIndex);
1689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ beq(&done);
1690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(feedback_map, FieldMemOperand(r8, HeapObject::kMapOffset));
1691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex);
1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bne(&check_allocation_site);
1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If the weak cell is cleared, we have a new chance to become monomorphic.
1695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(weak_value, &initialize);
1696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ b(&megamorphic);
1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&check_allocation_site);
1699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If we came here, we need to see if we are the array function.
1700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If we didn't have a matching function, and we didn't find the megamorph
1701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // sentinel, then we have in the slot either some other function or an
1702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // AllocationSite.
1703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex);
1704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bne(&miss);
1705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Make sure the function is the Array() function
1707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8);
1708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(r4, r8);
1709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bne(&megamorphic);
1710f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ b(&done);
1711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
1713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
1715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // megamorphic.
1716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(r8, Heap::kuninitialized_symbolRootIndex);
1717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&initialize);
1718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // MegamorphicSentinel is an immortal immovable object (undefined) so no
1719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // write-barrier is needed.
1720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&megamorphic);
1721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ SmiToPtrArrayOffset(r8, r6);
1722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ add(r8, r5, r8);
1723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ StoreP(ip, FieldMemOperand(r8, FixedArray::kHeaderSize), r0);
1725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ jmp(&done);
1726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // An uninitialized cache is patched with the function
1728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&initialize);
1729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Make sure the function is the Array() function.
1731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8);
1732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(r4, r8);
1733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bne(&not_array_function);
1734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The target function is the Array constructor,
1736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create an AllocationSite if we don't already have it, store it in the
1737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // slot.
1738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CreateAllocationSiteStub create_stub(masm->isolate());
1739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallStubInRecordCallTarget(masm, &create_stub);
1740f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ b(&done);
1741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&not_array_function);
1743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CreateWeakCellStub weak_cell_stub(masm->isolate());
1745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallStubInRecordCallTarget(masm, &weak_cell_stub);
174613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1747f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  __ bind(&done);
174813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1749f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Increment the call count for all function calls.
175013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ SmiToPtrArrayOffset(r8, r6);
175113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ add(r8, r5, r8);
175213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
175313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ LoadP(r7, FieldMemOperand(r8, count_offset));
175413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
175513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ StoreP(r7, FieldMemOperand(r8, count_offset), r0);
1756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CallConstructStub::Generate(MacroAssembler* masm) {
1760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r3 : number of arguments
1761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r4 : the function to call
1762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r5 : feedback vector
1763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r6 : slot in feedback vector (Smi, for RecordCallTarget)
1764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label non_function;
1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check that the function is not a smi.
1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfSmi(r4, &non_function);
1768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check that the function is a JSFunction.
1769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE);
1770014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bne(&non_function);
1771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1772014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenerateRecordCallTarget(masm);
1773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ SmiToPtrArrayOffset(r8, r6);
1775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ add(r8, r5, r8);
1776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Put the AllocationSite from the feedback vector into r5, or undefined.
1777014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize));
1778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset));
1779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
1780014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(ISELECT)) {
1781014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
1782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(eq, r5, r5, r8);
1783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label feedback_register_initialized;
1785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ beq(&feedback_register_initialized);
1786014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
1787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&feedback_register_initialized);
1788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ AssertUndefinedOrAllocationSite(r5, r8);
1791958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Pass function as new target.
1793014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mr(r6, r4);
1794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Tail call to the function-specific construct stub (still in the caller
1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // context at this point).
1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
1798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kConstructStubOffset));
1799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ addi(ip, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
1800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpToJSEntry(ip);
1801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&non_function);
1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mr(r6, r4);
1804014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1805958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1806958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1807958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1808958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// StringCharCodeAtGenerator
1809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
1810958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If the receiver is a smi trigger the non-string case.
1811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (check_mode_ == RECEIVER_IS_UNKNOWN) {
1812958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfSmi(object_, receiver_not_string_);
1813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Fetch the instance type of the receiver into result register.
1815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
1816958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
1817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If the receiver is not a string trigger the non-string case.
1818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ andi(r0, result_, Operand(kIsNotStringMask));
1819958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bne(receiver_not_string_, cr0);
1820958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1822958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If the index is non-smi trigger the non-smi case.
1823958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotSmi(index_, &index_not_smi_);
1824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&got_smi_index_);
1825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1826958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check for index out of range.
1827958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(ip, FieldMemOperand(object_, String::kLengthOffset));
1828958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpl(ip, index_);
1829958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ ble(index_out_of_range_);
1830958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1831958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(index_);
1832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1833958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StringCharLoadGenerator::Generate(masm, object_, index_, result_,
1834958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    &call_runtime_);
1835958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1836958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiTag(result_);
1837958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&exit_);
1838958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1839958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1840958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1841958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringCharCodeAtGenerator::GenerateSlow(
1842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MacroAssembler* masm, EmbedMode embed_mode,
1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const RuntimeCallHelper& call_helper) {
1844958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
1845958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1846958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Index is not a smi.
1847958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&index_not_smi_);
1848958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If index is a heap number, try converting it to an integer.
1849958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CheckMap(index_, result_, Heap::kHeapNumberMapRootIndex, index_not_number_,
1850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              DONT_DO_SMI_CHECK);
1851958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  call_helper.BeforeCall(masm);
1852014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (embed_mode == PART_OF_IC_HANDLER) {
1853014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(LoadWithVectorDescriptor::VectorRegister(),
1854014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            LoadWithVectorDescriptor::SlotRegister(), object_, index_);
1855014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // index_ is consumed by runtime conversion function.
1857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(object_, index_);
1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
185913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ CallRuntime(Runtime::kNumberToSmi);
1860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Save the conversion result before the pop instructions below
1861958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // have a chance to overwrite it.
1862958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(index_, r3);
1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (embed_mode == PART_OF_IC_HANDLER) {
1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Pop(LoadWithVectorDescriptor::VectorRegister(),
1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           LoadWithVectorDescriptor::SlotRegister(), object_);
1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ pop(object_);
1868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1869958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Reload the instance type.
1870958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
1871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
1872958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  call_helper.AfterCall(masm);
1873958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If index is still not a smi, it must be out of range.
1874958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotSmi(index_, index_out_of_range_);
1875958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Otherwise, return to the fast path.
1876958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&got_smi_index_);
1877958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1878958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Call runtime. We get here when the receiver is a string and the
1879958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // index is a number, but the code of getting the actual character
1880958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // is too complex (e.g., when the string needs to be flattened).
1881958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&call_runtime_);
1882958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  call_helper.BeforeCall(masm);
1883958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiTag(index_);
1884958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(object_, index_);
1885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallRuntime(Runtime::kStringCharCodeAtRT);
1886958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Move(result_, r3);
1887958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  call_helper.AfterCall(masm);
1888958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&exit_);
1889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1890958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
1891958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1892958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1893958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
1894958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                   Register left,
1895958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                   Register right,
1896958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                   Register scratch1,
1897958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                   Register scratch2) {
1898958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register length = scratch1;
1899958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1900958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare lengths.
1901958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label strings_not_equal, check_zero_length;
1902958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(length, FieldMemOperand(left, String::kLengthOffset));
1903958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
1904958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(length, scratch2);
1905958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&check_zero_length);
1906958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&strings_not_equal);
1907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadSmiLiteral(r3, Smi::FromInt(NOT_EQUAL));
1908958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
1909958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1910958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if the length is zero.
1911958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label compare_chars;
1912958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&check_zero_length);
1913958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kSmiTag == 0);
1914958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(length, Operand::Zero());
1915958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&compare_chars);
1916958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
1917958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
1918958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1919958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare characters.
1920958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&compare_chars);
1921958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2,
1922958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  &strings_not_equal);
1923958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1924958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Characters are equal.
1925958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
1926958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
1927958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1928958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1929958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateCompareFlatOneByteStrings(
1931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Register left, Register right, Register scratch1,
1932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register scratch2, Register scratch3) {
1933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label result_not_equal, compare_lengths;
1934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Find minimum length and length difference.
1935958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset));
1936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
1937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC);
1938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register length_delta = scratch3;
1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(ISELECT)) {
1940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(gt, scratch1, scratch2, scratch1, cr0);
1941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label skip;
1943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ble(&skip, cr0);
1944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mr(scratch1, scratch2);
1945014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&skip);
1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1947958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register min_length = scratch1;
1948958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kSmiTag == 0);
1949958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(min_length, Operand::Zero());
1950958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(&compare_lengths);
1951958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1952958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare loop.
1953958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2,
1954958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  &result_not_equal);
1955958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare lengths - strings up to min-length are equal.
1957958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&compare_lengths);
1958958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
1959958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Use length_delta as result if it's zero.
1960958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r3, length_delta);
1961958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(r3, Operand::Zero());
1962958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&result_not_equal);
1963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Conditionally update the result based either on length_delta or
1964958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the last comparion performed in the loop above.
1965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(ISELECT)) {
1966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadSmiLiteral(r4, Smi::FromInt(GREATER));
1967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadSmiLiteral(r5, Smi::FromInt(LESS));
1968014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(eq, r3, r0, r4);
1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(lt, r3, r5, r3);
1970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
1971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
1972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label less_equal, equal;
1973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ ble(&less_equal);
1974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
1975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
1976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&less_equal);
1977014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ beq(&equal);
1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
1979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&equal);
1980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
1981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1982958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1983958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StringHelper::GenerateOneByteCharsCompareLoop(
1986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Register left, Register right, Register length,
1987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register scratch1, Label* chars_not_equal) {
1988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Change index to run from -length to -1 by adding length to string
1989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // start. This means that loop ends when index reaches zero, which
1990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // doesn't need an additional compare.
1991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(length);
1992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(scratch1, length,
1993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
1994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(left, left, scratch1);
1995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(right, right, scratch1);
1996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ subfic(length, length, Operand::Zero());
1997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register index = length;  // index = -length;
1998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare loop.
2000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label loop;
2001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&loop);
2002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbzx(scratch1, MemOperand(left, index));
2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbzx(r0, MemOperand(right, index));
2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(scratch1, r0);
2005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(chars_not_equal);
2006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ addi(index, index, Operand(1));
2007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(index, Operand::Zero());
2008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&loop);
2009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
2013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // ----------- S t a t e -------------
2014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r4    : left
2015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r3    : right
2016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- lr    : return address
2017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // -----------------------------------
2018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load r5 with the allocation site.  We stick an undefined dummy value here
2020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // and replace it with the real allocation site later when we instantiate this
2021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
202213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Move(r5, isolate()->factory()->undefined_value());
2023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Make sure that we actually patched the allocation site.
2025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (FLAG_debug_code) {
2026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ TestIfSmi(r5, r0);
2027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Assert(ne, kExpectedAllocationSite, cr0);
2028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ push(r5);
2029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset));
2030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadRoot(ip, Heap::kAllocationSiteMapRootIndex);
2031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmp(r5, ip);
2032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ pop(r5);
2033958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Assert(eq, kExpectedAllocationSite);
2034958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2035958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2036958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Tail call into the stub that handles binary operations with allocation
2037958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // sites.
2038958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  BinaryOpWithAllocationSiteStub stub(isolate(), state());
2039958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ TailCallStub(&stub);
2040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateBooleans(MacroAssembler* masm) {
2044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(CompareICState::BOOLEAN, state());
2045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label miss;
2046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CheckMap(r4, r5, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
2048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CheckMap(r3, r6, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
2049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!Token::IsEqualityOp(op())) {
2050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(r4, FieldMemOperand(r4, Oddball::kToNumberOffset));
2051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ AssertSmi(r4);
2052109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset));
2053109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ AssertSmi(r3);
2054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2055109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ sub(r3, r4, r3);
2056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Ret();
2057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&miss);
2059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  GenerateMiss(masm);
2060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2063958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateSmis(MacroAssembler* masm) {
2064958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(state() == CompareICState::SMI);
2065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss;
2066958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ orx(r5, r4, r3);
2067958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotSmi(r5, &miss);
2068958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (GetCondition() == eq) {
2070958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // For equality we do not care about the sign of the result.
2071958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // __ sub(r3, r3, r4, SetCC);
2072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ sub(r3, r3, r4);
2073958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Untag before subtracting to avoid handling overflow.
2075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ SmiUntag(r4);
2076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ SmiUntag(r3);
2077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ sub(r3, r4, r3);
2078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
2082958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
2083958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2084958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2085958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2086958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateNumbers(MacroAssembler* masm) {
2087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(state() == CompareICState::NUMBER);
2088958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2089958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label generic_stub;
2090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label unordered, maybe_undefined1, maybe_undefined2;
2091958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss;
2092958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label equal, less_than;
2093958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2094958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (left() == CompareICState::SMI) {
2095958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfNotSmi(r4, &miss);
2096958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2097958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (right() == CompareICState::SMI) {
2098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfNotSmi(r3, &miss);
2099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Inlining the double comparison and falling back to the general compare
2102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // stub if NaN is involved.
2103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Load left and right operand.
2104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label done, left, left_smi, right_smi;
2105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(r3, &right_smi);
2106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CheckMap(r3, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined1,
2107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              DONT_DO_SMI_CHECK);
2108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lfd(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
2109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&left);
2110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&right_smi);
2111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiToDouble(d1, r3);
2112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&left);
2114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(r4, &left_smi);
2115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CheckMap(r4, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined2,
2116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              DONT_DO_SMI_CHECK);
2117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lfd(d0, FieldMemOperand(r4, HeapNumber::kValueOffset));
2118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ b(&done);
2119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&left_smi);
2120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiToDouble(d0, r4);
2121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&done);
2123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare operands
2125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ fcmpu(d0, d1);
2126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Don't base result on status bits when a NaN is involved.
2128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bunordered(&unordered);
2129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return a result of -1, 0, or 1, based on status bits.
2131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(ISELECT)) {
2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(EQUAL == 0);
2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r4, Operand(GREATER));
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r5, Operand(LESS));
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(eq, r3, r0, r4);
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(lt, r3, r5, r3);
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ beq(&equal);
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ blt(&less_than);
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    //  assume greater than
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r3, Operand(GREATER));
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&equal);
2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r3, Operand(EQUAL));
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&less_than);
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ li(r3, Operand(LESS));
2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&unordered);
2153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&generic_stub);
2154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  CompareICStub stub(isolate(), op(), CompareICState::GENERIC,
2155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     CompareICState::GENERIC, CompareICState::GENERIC);
2156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
2157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&maybe_undefined1);
2159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (Token::IsOrderedRelationalCompareOp(op())) {
2160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
2161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bne(&miss);
2162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfSmi(r4, &unordered);
2163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE);
2164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bne(&maybe_undefined2);
2165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ b(&unordered);
2166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&maybe_undefined2);
2169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (Token::IsOrderedRelationalCompareOp(op())) {
2170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CompareRoot(r4, Heap::kUndefinedValueRootIndex);
2171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&unordered);
2172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
2175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
2176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) {
2180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(state() == CompareICState::INTERNALIZED_STRING);
2181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss, not_equal;
2182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Registers containing left and right operands respectively.
2184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register left = r4;
2185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register right = r3;
2186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp1 = r5;
2187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp2 = r6;
2188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both operands are heap objects.
2190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfEitherSmi(left, right, &miss);
2191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both operands are symbols.
2193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
2194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
2195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
2196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
2197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
2198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ orx(tmp1, tmp1, tmp2);
2199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask));
2200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&miss, cr0);
2201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Internalized strings are compared by identity.
2203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(left, right);
2204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&not_equal);
2205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Make sure r3 is non-zero. At this point input operands are
2206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // guaranteed to be non-zero.
2207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(right.is(r3));
2208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(EQUAL == 0);
2209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kSmiTag == 0);
2210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
2211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_equal);
2212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
2215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
2216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateUniqueNames(MacroAssembler* masm) {
2220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(state() == CompareICState::UNIQUE_NAME);
2221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(GetCondition() == eq);
2222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss;
2223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Registers containing left and right operands respectively.
2225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register left = r4;
2226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register right = r3;
2227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp1 = r5;
2228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp2 = r6;
2229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both operands are heap objects.
2231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfEitherSmi(left, right, &miss);
2232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both operands are unique names. This leaves the instance
2234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // types loaded in tmp1 and tmp2.
2235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
2236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
2237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
2238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
2239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotUniqueNameInstanceType(tmp1, &miss);
2241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfNotUniqueNameInstanceType(tmp2, &miss);
2242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Unique names are compared by identity.
2244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(left, right);
2245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&miss);
2246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Make sure r3 is non-zero. At this point input operands are
2247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // guaranteed to be non-zero.
2248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(right.is(r3));
2249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(EQUAL == 0);
2250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kSmiTag == 0);
2251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
2252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
2255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
2256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateStrings(MacroAssembler* masm) {
2260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(state() == CompareICState::STRING);
2261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss, not_identical, is_symbol;
2262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool equality = Token::IsEqualityOp(op());
2264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Registers containing left and right operands respectively.
2266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register left = r4;
2267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register right = r3;
2268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp1 = r5;
2269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp2 = r6;
2270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp3 = r7;
2271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register tmp4 = r8;
2272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both operands are heap objects.
2274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfEitherSmi(left, right, &miss);
2275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both operands are strings. This leaves the instance
2277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // types loaded in tmp1 and tmp2.
2278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
2279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
2280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
2281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
2282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kNotStringTag != 0);
2283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ orx(tmp3, tmp1, tmp2);
2284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ andi(r0, tmp3, Operand(kIsNotStringMask));
2285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&miss, cr0);
2286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Fast check for identical strings.
2288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmp(left, right);
2289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(EQUAL == 0);
2290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kSmiTag == 0);
2291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&not_identical);
2292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
2293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_identical);
2295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Handle not identical strings.
2297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both strings are internalized strings. If they are, we're done
2299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // because we already know they are not identical. We know they are both
2300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // strings.
2301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (equality) {
2302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(GetCondition() == eq);
2303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    STATIC_ASSERT(kInternalizedTag == 0);
2304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ orx(tmp3, tmp1, tmp2);
2305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ andi(r0, tmp3, Operand(kIsNotInternalizedMask));
2306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Make sure r3 is non-zero. At this point input operands are
2307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // guaranteed to be non-zero.
2308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(right.is(r3));
2309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret(eq, cr0);
2310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check that both strings are sequential one-byte.
2313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label runtime;
2314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4,
2315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                    &runtime);
2316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compare flat one-byte strings. Returns when done.
2318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (equality) {
2319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1,
2320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                  tmp2);
2321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1,
2323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                    tmp2, tmp3);
2324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Handle more complex cases in runtime.
2327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&runtime);
2328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (equality) {
23293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    {
23303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
23313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ Push(left, right);
23323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      __ CallRuntime(Runtime::kStringEqual);
23333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
23343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ LoadRoot(r4, Heap::kTrueValueRootIndex);
23353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ sub(r3, r3, r4);
23363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Ret();
2337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
23383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    __ Push(left, right);
2339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ TailCallRuntime(Runtime::kStringCompare);
2340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
2343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
2344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateReceivers(MacroAssembler* masm) {
2348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(CompareICState::RECEIVER, state());
2349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss;
2350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ and_(r5, r4, r3);
2351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(r5, &miss);
2352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
2354014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r3, r5, r5, FIRST_JS_RECEIVER_TYPE);
2355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ blt(&miss);
2356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CompareObjectType(r4, r5, r5, FIRST_JS_RECEIVER_TYPE);
2357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ blt(&miss);
2358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(GetCondition() == eq);
2360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ sub(r3, r3, r4);
2361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
2364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
2365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CompareICStub::GenerateKnownReceivers(MacroAssembler* masm) {
2369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label miss;
2370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Handle<WeakCell> cell = Map::WeakCellForMap(known_map_);
2371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ and_(r5, r4, r3);
2372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfSmi(r5, &miss);
2373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ GetWeakValue(r7, cell);
2374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
2375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset));
2376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(r5, r7);
2377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&miss);
2378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(r6, r7);
2379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(&miss);
2380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2381014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (Token::IsEqualityOp(op())) {
2382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ sub(r3, r3, r4);
2383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Ret();
2384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
2385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (op() == Token::LT || op() == Token::LTE) {
2386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LoadSmiLiteral(r5, Smi::FromInt(GREATER));
2387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } else {
2388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      __ LoadSmiLiteral(r5, Smi::FromInt(LESS));
2389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Push(r4, r3, r5);
2391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ TailCallRuntime(Runtime::kCompare);
2392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&miss);
2395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateMiss(masm);
2396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompareICStub::GenerateMiss(MacroAssembler* masm) {
2400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
2401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Call the runtime system in a fresh internal frame.
2402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
2403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Push(r4, r3);
2404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Push(r4, r3);
2405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadSmiLiteral(r0, Smi::FromInt(op()));
2406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ push(r0);
2407014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallRuntime(Runtime::kCompareIC_Miss);
2408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Compute the entry point of the rewritten stub.
2409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
2410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Restore registers.
2411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Pop(r4, r3);
2412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpToJSEntry(r5);
2415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// This stub is paired with DirectCEntryStub::GenerateCall
2419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DirectCEntryStub::Generate(MacroAssembler* masm) {
2420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Place the return address on the stack, making the call
2421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // GC safe. The RegExp backend also relies on this.
2422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mflr(r0);
2423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
2424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Call(ip);  // Call the C++ function.
2425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
2426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mtlr(r0);
2427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blr();
2428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) {
2432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (ABI_USES_FUNCTION_DESCRIPTORS) {
2433109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // AIX/PPC64BE Linux use a function descriptor.
2434109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
2435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(ip, MemOperand(target, 0));  // Instruction address
2436109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // ip needs to be set for DirectCEentryStub::Generate, and also
2438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // for ABI_CALL_VIA_IP.
2439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Move(ip, target);
2440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  intptr_t code = reinterpret_cast<intptr_t>(GetCode().location());
2443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r0, Operand(code, RelocInfo::CODE_TARGET));
2444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Call(r0);  // Call the stub.
2445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NameDictionaryLookupStub::GenerateNegativeLookup(
2449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, Label* miss, Label* done, Register receiver,
2450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register properties, Handle<Name> name, Register scratch0) {
2451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(name->IsUniqueName());
2452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If names of slots in range from 1 to kProbes - 1 for the hash value are
2453958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // not equal to the name and kProbes-th slot is not used (its name is the
2454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // undefined value), it guarantees the hash table doesn't contain the
2455958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // property. It's true even if some slots represent deleted properties
2456958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // (their names are the hole value).
2457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < kInlinedProbes; i++) {
2458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // scratch0 points to properties hash.
2459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Compute the masked index: (hash + i + i * i) & mask.
2460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register index = scratch0;
2461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Capacity is smi 2^n.
2462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(index, FieldMemOperand(properties, kCapacityOffset));
2463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ subi(index, index, Operand(1));
2464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadSmiLiteral(
2465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        ip, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i)));
2466958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ and_(index, index, ip);
2467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Scale the index by multiplying by the entry size.
2469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(NameDictionary::kEntrySize == 3);
2470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ ShiftLeftImm(ip, index, Operand(1));
2471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ add(index, index, ip);  // index *= 3.
2472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register entity_name = scratch0;
2474958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Having undefined at this place means the name is not contained.
2475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Register tmp = properties;
2476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ SmiToPtrArrayOffset(ip, index);
2477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ add(tmp, properties, ip);
2478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
2479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(!tmp.is(entity_name));
2481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
2482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmp(entity_name, tmp);
2483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(done);
2484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Load the hole ready for use below:
2486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
2487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Stop if found the property.
2489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Cmpi(entity_name, Operand(Handle<Name>(name)), r0);
2490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(miss);
2491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label good;
2493958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmp(entity_name, tmp);
2494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&good);
2495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Check if the entry name is not a unique name.
2497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
2498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ lbz(entity_name, FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
2499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfNotUniqueNameInstanceType(entity_name, miss);
2500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&good);
2501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Restore the properties.
2503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(properties,
2504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             FieldMemOperand(receiver, JSObject::kPropertiesOffset));
2505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int spill_mask = (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() |
2508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                          r5.bit() | r4.bit() | r3.bit());
2509958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mflr(r0);
2511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ MultiPush(spill_mask);
2512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
2514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r4, Operand(Handle<Name>(name)));
2515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP);
2516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CallStub(&stub);
2517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ cmpi(r3, Operand::Zero());
2518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ MultiPop(spill_mask);  // MultiPop does not touch condition flags
2520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mtlr(r0);
2521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ beq(done);
2523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bne(miss);
2524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
2527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
2528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // we cannot call anything that could cause a GC from this stub.
2529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Registers:
2530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  result: NameDictionary to probe
2531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  r4: key
2532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  dictionary: NameDictionary to probe.
2533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  index: will hold an index of entry if lookup is successful.
2534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //         might alias with result_.
2535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Returns:
2536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  result_ is zero if lookup failed, non zero otherwise.
2537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register result = r3;
2539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register dictionary = r3;
2540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register key = r4;
2541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register index = r5;
2542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register mask = r6;
2543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register hash = r7;
2544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register undefined = r8;
2545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register entry_key = r9;
2546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register scratch = r9;
2547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
2549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(mask, FieldMemOperand(dictionary, kCapacityOffset));
2551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ SmiUntag(mask);
2552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ subi(mask, mask, Operand(1));
2553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ lwz(hash, FieldMemOperand(key, Name::kHashFieldOffset));
2555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
2557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = kInlinedProbes; i < kTotalProbes; i++) {
2559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Compute the masked index: (hash + i + i * i) & mask.
2560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Capacity is smi 2^n.
2561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (i > 0) {
2562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Add the probe offset (i + i * i) left shifted to avoid right shifting
2563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // the hash in a separate instruction. The value hash + i + i * i is right
2564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // shifted in the following and instruction.
2565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(NameDictionary::GetProbeOffset(i) <
2566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             1 << (32 - Name::kHashFieldOffset));
2567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ addi(index, hash,
2568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift));
2569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
2570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ mr(index, hash);
2571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ srwi(r0, index, Operand(Name::kHashShift));
2573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ and_(index, mask, r0);
2574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Scale the index by multiplying by the entry size.
2576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    STATIC_ASSERT(NameDictionary::kEntrySize == 3);
2577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ ShiftLeftImm(scratch, index, Operand(1));
2578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ add(index, index, scratch);  // index *= 3.
2579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2));
2581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ add(index, dictionary, scratch);
2582958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset));
2583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Having undefined at this place means the name is not contained.
2585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmp(entry_key, undefined);
2586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&not_in_dictionary);
2587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Stop if found the property.
2589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ cmp(entry_key, key);
2590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ beq(&in_dictionary);
2591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) {
2593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Check if the entry name is not a unique name.
2594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ LoadP(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
2595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ lbz(entry_key, FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
2596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      __ JumpIfNotUniqueNameInstanceType(entry_key, &maybe_in_dictionary);
2597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
2598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&maybe_in_dictionary);
2601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If we are doing negative lookup then probing failure should be
2602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // treated as a lookup success. For positive lookup probing failure
2603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // should be treated as lookup failure.
2604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (mode() == POSITIVE_LOOKUP) {
2605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ li(result, Operand::Zero());
2606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Ret();
2607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&in_dictionary);
2610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(result, Operand(1));
2611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&not_in_dictionary);
2614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ li(result, Operand::Zero());
2615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
2620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Isolate* isolate) {
2621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs);
2622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  stub1.GetCode();
2623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Hydrogen code stubs need stub2 at snapshot time.
2624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StoreBufferOverflowStub stub2(isolate, kSaveFPRegs);
2625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  stub2.GetCode();
2626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Takes the input in 3 registers: address_ value_ and object_.  A pointer to
2630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the value has just been written into the object, now this stub makes sure
2631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// we keep the GC informed.  The word in the object where the value has been
2632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// written is in the address register.
2633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::Generate(MacroAssembler* masm) {
2634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label skip_to_incremental_noncompacting;
2635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label skip_to_incremental_compacting;
2636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The first two branch instructions are generated with labels so as to
2638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // get the offset fixed up correctly by the bind(Label*) call.  We patch
2639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // it back and forth between branch condition True and False
2640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // when we start and stop incremental heap marking.
2641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // See RecordWriteStub::Patch for details.
2642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Clear the bit, branch on True for NOP action initially
2644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ crclr(Assembler::encode_crbit(cr2, CR_LT));
2645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blt(&skip_to_incremental_noncompacting, cr2);
2646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ blt(&skip_to_incremental_compacting, cr2);
2647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (remembered_set_action() == EMIT_REMEMBERED_SET) {
2649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
2650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           MacroAssembler::kReturnAtEnd);
2651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2653958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2654958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&skip_to_incremental_noncompacting);
2655958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateIncremental(masm, INCREMENTAL);
2656958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2657958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&skip_to_incremental_compacting);
2658958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  GenerateIncremental(masm, INCREMENTAL_COMPACTION);
2659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
2661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Will be checked in IncrementalMarking::ActivateGeneratedStub.
2662958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // patching not required on PPC as the initial path is effectively NOP
2663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2664958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2665958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2666958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
2667958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  regs_.Save(masm);
2668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (remembered_set_action() == EMIT_REMEMBERED_SET) {
2670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label dont_need_remembered_set;
2671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0));
2673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ JumpIfNotInNewSpace(regs_.scratch0(),  // Value.
2674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           regs_.scratch0(), &dont_need_remembered_set);
2675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2676109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ JumpIfInNewSpace(regs_.object(), regs_.scratch0(),
2677109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                        &dont_need_remembered_set);
2678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // First notify the incremental marker if necessary, then update the
2680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // remembered set.
2681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CheckNeedsToInformIncrementalMarker(
2682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        masm, kUpdateRememberedSetOnNoNeedToInformIncrementalMarker, mode);
2683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    InformIncrementalMarker(masm);
2684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    regs_.Restore(masm);
2685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
2686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           MacroAssembler::kReturnAtEnd);
2687958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2688958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&dont_need_remembered_set);
2689958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2690958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2691958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CheckNeedsToInformIncrementalMarker(
2692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
2693958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  InformIncrementalMarker(masm);
2694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  regs_.Restore(masm);
2695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2696958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2697958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2698958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) {
2700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode());
2701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int argument_count = 3;
2702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ PrepareCallCFunction(argument_count, regs_.scratch0());
2703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register address =
2704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      r3.is(regs_.address()) ? regs_.scratch0() : regs_.address();
2705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!address.is(regs_.object()));
2706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!address.is(r3));
2707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(address, regs_.address());
2708958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r3, regs_.object());
2709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(r4, address);
2710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
2711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2712958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AllowExternalCallThatCantCauseGC scope(masm);
2713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ CallCFunction(
2714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ExternalReference::incremental_marking_record_write_function(isolate()),
2715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      argument_count);
2716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode());
2717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid RecordWriteStub::CheckNeedsToInformIncrementalMarker(
2721958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MacroAssembler* masm, OnNoNeedToInformIncrementalMarker on_no_need,
2722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Mode mode) {
2723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label on_black;
2724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label need_incremental;
2725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Label need_incremental_pop_scratch;
2726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Let's look at the color of the object:  If it is not black we don't have
2728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // to inform the incremental marker.
2729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black);
2730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  regs_.Restore(masm);
2732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
2733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
2734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           MacroAssembler::kReturnAtEnd);
2735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2736958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Ret();
2737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2738958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&on_black);
2740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2741958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Get the value from the slot.
2742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0));
2743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (mode == INCREMENTAL_COMPACTION) {
2745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Label ensure_not_white;
2746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CheckPageFlag(regs_.scratch0(),  // Contains value.
2748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     regs_.scratch1(),  // Scratch.
2749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     MemoryChunk::kEvacuationCandidateMask, eq,
2750958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     &ensure_not_white);
2751958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ CheckPageFlag(regs_.object(),
2753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     regs_.scratch1(),  // Scratch.
2754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     MemoryChunk::kSkipEvacuationSlotsRecordingMask, eq,
2755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                     &need_incremental);
2756958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2757958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ bind(&ensure_not_white);
2758958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2759958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2760958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // We need extra registers for this, so we push the object and the address
2761958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // register temporarily.
2762958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Push(regs_.object(), regs_.address());
2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ JumpIfWhite(regs_.scratch0(),  // The value.
2764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 regs_.scratch1(),  // Scratch.
2765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 regs_.object(),    // Scratch.
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 regs_.address(),   // Scratch.
2767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                 &need_incremental_pop_scratch);
2768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Pop(regs_.object(), regs_.address());
2769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  regs_.Restore(masm);
2771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
2772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
2773958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           MacroAssembler::kReturnAtEnd);
2774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
2775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ Ret();
2776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2778958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&need_incremental_pop_scratch);
2779958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Pop(regs_.object(), regs_.address());
2780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ bind(&need_incremental);
2782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2783958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Fall through when we need to inform the incremental marker.
2784958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2785958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2786958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2787958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
2788958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CEntryStub ces(isolate(), 1, kSaveFPRegs);
2789958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
2790958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int parameter_count_offset =
27913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      StubFailureTrampolineFrameConstants::kArgumentsLengthOffset;
2792958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ LoadP(r4, MemOperand(fp, parameter_count_offset));
2793958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (function_mode() == JS_FUNCTION_STUB_MODE) {
2794958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ addi(r4, r4, Operand(1));
2795958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
2796958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
2797958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ slwi(r4, r4, Operand(kPointerSizeLog2));
2798958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ add(sp, sp, r4);
2799958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ Ret();
2800958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
2801958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2802109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
2803109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (masm->isolate()->function_entry_hook() != NULL) {
2804109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    PredictableCodeSizeScope predictable(masm,
2805109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if V8_TARGET_ARCH_PPC64
2806109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                         14 * Assembler::kInstrSize);
2807109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else
2808109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                         11 * Assembler::kInstrSize);
2809109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
2810109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    ProfileEntryHookStub stub(masm->isolate());
2811109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ mflr(r0);
2812109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Push(r0, ip);
2813109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CallStub(&stub);
2814109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Pop(r0, ip);
2815109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ mtlr(r0);
2816109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
28178389745919cae02139ddc085a63c00d024269cf2Ben Murdoch}
2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2820109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ProfileEntryHookStub::Generate(MacroAssembler* masm) {
2821109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // The entry hook is a "push lr, ip" instruction, followed by a call.
2822109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int32_t kReturnAddressDistanceFromFunctionStart =
2823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      Assembler::kCallTargetAddressOffset + 3 * Assembler::kInstrSize;
2824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // This should contain all kJSCallerSaved registers.
2826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const RegList kSavedRegs = kJSCallerSaved |  // Caller saved registers.
2827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                             r15.bit();        // Saved stack pointer.
2828f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
2829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // We also save lr, so the count here is one higher than the mask indicates.
2830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int32_t kNumSavedRegs = kNumJSCallerSaved + 2;
2831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Save all caller-save registers as this may be called from anywhere.
2833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mflr(ip);
2834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ MultiPush(kSavedRegs | ip.bit());
2835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Compute the function's address for the first argument.
2837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ subi(r3, ip, Operand(kReturnAddressDistanceFromFunctionStart));
2838109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // The caller's return address is two slots above the saved temporaries.
2840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Grab that for the second argument to the hook.
2841109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ addi(r4, sp, Operand((kNumSavedRegs + 1) * kPointerSize));
2842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2843109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Align the stack if necessary.
2844109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int frame_alignment = masm->ActivationFrameAlignment();
2845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (frame_alignment > kPointerSize) {
2846109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ mr(r15, sp);
2847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
2848109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
2849109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2850109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#if !defined(USE_SIMULATOR)
2852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  uintptr_t entry_hook =
2853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      reinterpret_cast<uintptr_t>(isolate()->function_entry_hook());
2854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#else
2855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Under the simulator we need to indirect the entry hook through a
2856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // trampoline function at a known address.
2857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
2858109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ExternalReference entry_hook = ExternalReference(
2859109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      &dispatcher, ExternalReference::BUILTIN_CALL, isolate());
2860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2861109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // It additionally takes an isolate as a third parameter
2862109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
2863109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
2864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2865109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mov(ip, Operand(entry_hook));
2866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2867109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (ABI_USES_FUNCTION_DESCRIPTORS) {
2868109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize));
2869109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(ip, MemOperand(ip, 0));
2870109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2871109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // ip set above, so nothing more to do for ABI_CALL_VIA_IP.
2872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2873109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // PPC LINUX ABI:
2874109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ li(r0, Operand::Zero());
2875109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize));
2876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2877109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Call(ip);
2878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2879109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize));
2880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2881109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Restore the stack pointer if needed.
2882109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (frame_alignment > kPointerSize) {
2883109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ mr(sp, r15);
2884109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2886109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Also pop lr to get Ret(0).
2887109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ MultiPop(kSavedRegs | ip.bit());
2888109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mtlr(ip);
2889109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Ret();
2890109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2893109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate <class T>
2894109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatch(MacroAssembler* masm,
2895109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                AllocationSiteOverrideMode mode) {
2896109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (mode == DISABLE_ALLOCATION_SITES) {
2897109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
2898109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TailCallStub(&stub);
2899109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else if (mode == DONT_OVERRIDE) {
2900109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int last_index =
2901109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
2902109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = 0; i <= last_index; ++i) {
2903109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
2904109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Cmpi(r6, Operand(kind), r0);
2905109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      T stub(masm->isolate(), kind);
2906109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ TailCallStub(&stub, eq);
2907109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
2908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2909109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // If we reached this point there is a problem.
2910109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Abort(kUnexpectedElementsKindInArrayConstructor);
2911109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2912109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    UNREACHABLE();
2913109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
29148389745919cae02139ddc085a63c00d024269cf2Ben Murdoch}
2915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2917109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void CreateArrayDispatchOneArgument(MacroAssembler* masm,
2918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                           AllocationSiteOverrideMode mode) {
2919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // r5 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
2920109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // r6 - kind (if mode != DISABLE_ALLOCATION_SITES)
2921109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // r3 - number of arguments
2922109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // r4 - constructor?
2923109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // sp[0] - last argument
2924109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label normal_sequence;
2925109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (mode == DONT_OVERRIDE) {
2926109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
2927109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
2928109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(FAST_ELEMENTS == 2);
2929109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
2930109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4);
2931109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
2932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // is the low bit set? If so, we are holey and that is good.
2934109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ andi(r0, r6, Operand(1));
2935109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ bne(&normal_sequence, cr0);
2936109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2938109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // look at the first argument
2939109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r8, MemOperand(sp, 0));
2940109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ cmpi(r8, Operand::Zero());
2941109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ beq(&normal_sequence);
2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2943109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (mode == DISABLE_ALLOCATION_SITES) {
2944109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    ElementsKind initial = GetInitialFastElementsKind();
2945109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    ElementsKind holey_initial = GetHoleyElementsKind(initial);
2946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2947109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    ArraySingleArgumentConstructorStub stub_holey(
2948109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES);
2949109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TailCallStub(&stub_holey);
29508389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
2951109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ bind(&normal_sequence);
2952109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    ArraySingleArgumentConstructorStub stub(masm->isolate(), initial,
2953109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                            DISABLE_ALLOCATION_SITES);
2954109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TailCallStub(&stub);
2955109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else if (mode == DONT_OVERRIDE) {
2956109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // We are going to create a holey array, but our kind is non-holey.
2957109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Fix kind and retry (only if we have an allocation site in the slot).
2958109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ addi(r6, r6, Operand(1));
29598389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
2960109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (FLAG_debug_code) {
2961109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ LoadP(r8, FieldMemOperand(r5, 0));
2962109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
2963109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ Assert(eq, kExpectedAllocationSite);
2964109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
2965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2966109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Save the resulting elements kind in type info. We can't just store r6
2967109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // in the AllocationSite::transition_info field because elements kind is
2968109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // restricted to a portion of the field...upper bits need to be left alone.
2969109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
2970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset));
2971109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ AddSmiLiteral(r7, r7, Smi::FromInt(kFastElementsKindPackedToHoley), r0);
2972109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ StoreP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset),
2973109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch              r0);
2974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2975109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ bind(&normal_sequence);
2976109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    int last_index =
2977109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
2978109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    for (int i = 0; i <= last_index; ++i) {
2979109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
2980109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ mov(r0, Operand(kind));
2981109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ cmp(r6, r0);
2982109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
2983109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      __ TailCallStub(&stub, eq);
2984109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
2985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2986109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // If we reached this point there is a problem.
2987109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Abort(kUnexpectedElementsKindInArrayConstructor);
2988109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
2989109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    UNREACHABLE();
2990109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2991109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
2992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2994109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochtemplate <class T>
2995109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochstatic void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
2996109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int to_index =
2997109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
2998109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = 0; i <= to_index; ++i) {
2999109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
3000109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    T stub(isolate, kind);
3001109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    stub.GetCode();
3002109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
3003109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      T stub1(isolate, kind, DISABLE_ALLOCATION_SITES);
3004109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      stub1.GetCode();
3005109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
3006109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3007109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
301013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
3011109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
3012109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      isolate);
301313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ArrayNArgumentsConstructorStub stub(isolate);
301413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  stub.GetCode();
3015109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS};
3016109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  for (int i = 0; i < 2; i++) {
3017109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // For internal arrays we only need a few things
3018109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]);
3019109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    stubh1.GetCode();
3020109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
3021109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    stubh2.GetCode();
3022109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3023109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3024109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3025109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3026109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::GenerateDispatchToArrayStub(
3027109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    MacroAssembler* masm, AllocationSiteOverrideMode mode) {
3028c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Label not_zero_case, not_one_case;
3029c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ cmpi(r3, Operand::Zero());
3030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ bne(&not_zero_case);
3031c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
3032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3033c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ bind(&not_zero_case);
3034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ cmpi(r3, Operand(1));
3035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ bgt(&not_one_case);
3036c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CreateArrayDispatchOneArgument(masm, mode);
3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3038c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ bind(&not_one_case);
3039c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ArrayNArgumentsConstructorStub stub(masm->isolate());
3040c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ TailCallStub(&stub);
3041109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3044109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid ArrayConstructorStub::Generate(MacroAssembler* masm) {
3045109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // ----------- S t a t e -------------
3046109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- r3 : argc (only if argument_count() == ANY)
3047109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- r4 : constructor
3048109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- r5 : AllocationSite or undefined
3049109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- r6 : new target
3050109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- sp[0] : return address
3051109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- sp[4] : last argument
3052109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // -----------------------------------
3053958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3054109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
3055109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // The array construct code is only set for the global and natives
3056109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // builtin Array functions which always have maps.
3057958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3058109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Initial map for the builtin Array function should be a map.
3059109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(r7, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
3060109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Will both indicate a NULL and a Smi.
3061109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TestIfSmi(r7, r0);
3062109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0);
3063109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CompareObjectType(r7, r7, r8, MAP_TYPE);
3064109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
3065958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3066109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // We should either have undefined in r5 or a valid AllocationSite
3067109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ AssertUndefinedOrAllocationSite(r5, r7);
3068109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3069958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3070109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Enter the context of the Array function.
3071109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
3072958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3073109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label subclassing;
3074109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ cmp(r6, r4);
3075109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bne(&subclassing);
3076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3077109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label no_info;
3078109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Get the elements kind and case on that.
3079109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
3080109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ beq(&no_info);
3081958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3082109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r6, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset));
3083109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ SmiUntag(r6);
3084109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
3085109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ And(r6, r6, Operand(AllocationSite::ElementsKindBits::kMask));
3086109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
3087958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3088109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&no_info);
3089109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
3090958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3091109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&subclassing);
3092c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
3093c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ StorePX(r4, MemOperand(sp, r0));
3094c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ addi(r3, r3, Operand(3));
3095109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ Push(r6, r5);
3096109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate()));
3097109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3098958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3099958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3100109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm,
3101109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                                ElementsKind kind) {
3102109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ cmpli(r3, Operand(1));
3103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3104109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
3105109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ TailCallStub(&stub0, lt);
3106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
310713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  ArrayNArgumentsConstructorStub stubN(isolate());
3108109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ TailCallStub(&stubN, gt);
3109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3110109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (IsFastPackedElementsKind(kind)) {
3111109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // We might need to create a holey array
3112109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // look at the first argument
3113109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(r6, MemOperand(sp, 0));
3114109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ cmpi(r6, Operand::Zero());
3115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3116109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    InternalArraySingleArgumentConstructorStub stub1_holey(
3117109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        isolate(), GetHoleyElementsKind(kind));
3118109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TailCallStub(&stub1_holey, ne);
3119f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  }
3120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3121109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
3122109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ TailCallStub(&stub1);
3123109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
3124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
31258389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
3126109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochvoid InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
3127109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // ----------- S t a t e -------------
3128109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- r3 : argc
3129109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- r4 : constructor
3130109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- sp[0] : return address
3131109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //  -- sp[4] : last argument
3132109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // -----------------------------------
3133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3134109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
3135109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // The array construct code is only set for the global and natives
3136109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // builtin Array functions which always have maps.
3137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3138109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Initial map for the builtin Array function should be a map.
3139109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
3140109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // Will both indicate a NULL and a Smi.
3141109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ TestIfSmi(r6, r0);
3142109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0);
3143109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ CompareObjectType(r6, r6, r7, MAP_TYPE);
3144109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
3145f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  }
3146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3147109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Figure out the right elements kind
3148109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
3149109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Load the map's "bit field 2" into |result|.
3150109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ lbz(r6, FieldMemOperand(r6, Map::kBitField2Offset));
3151109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Retrieve elements_kind from bit field 2.
3152109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ DecodeField<Map::ElementsKindBits>(r6);
3153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3154109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (FLAG_debug_code) {
3155109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Label done;
3156109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ cmpi(r6, Operand(FAST_ELEMENTS));
3157109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ beq(&done);
3158109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ cmpi(r6, Operand(FAST_HOLEY_ELEMENTS));
3159109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ Assert(eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray);
3160109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ bind(&done);
3161109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3163109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Label fast_elements_case;
3164109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ cmpi(r6, Operand(FAST_ELEMENTS));
3165109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ beq(&fast_elements_case);
3166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  GenerateCase(masm, FAST_HOLEY_ELEMENTS);
3167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3168109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ bind(&fast_elements_case);
3169109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  GenerateCase(masm, FAST_ELEMENTS);
31708389745919cae02139ddc085a63c00d024269cf2Ben Murdoch}
3171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
3173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return ref0.address() - ref1.address();
3174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Calls an API function.  Allocates HandleScope, extracts returned value
3178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// from handle and propagates exceptions.  Restores context.  stack_space
3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// - space to be unwound on exit (includes the call JS arguments space and
3180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// the additional space allocated for the fast call).
3181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void CallApiFunctionAndReturn(MacroAssembler* masm,
3182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     Register function_address,
3183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     ExternalReference thunk_ref,
3184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     int stack_space,
3185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     MemOperand* stack_space_operand,
3186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     MemOperand return_value_operand,
3187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     MemOperand* context_restore_operand) {
3188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate = masm->isolate();
3189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference next_address =
3190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::handle_scope_next_address(isolate);
3191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int kNextOffset = 0;
3192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int kLimitOffset = AddressOffset(
3193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::handle_scope_limit_address(isolate), next_address);
3194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int kLevelOffset = AddressOffset(
3195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::handle_scope_level_address(isolate), next_address);
3196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Additional parameter is the address of the actual callback.
3198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function_address.is(r4) || function_address.is(r5));
3199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Register scratch = r6;
3200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate)));
3202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lbz(scratch, MemOperand(scratch, 0));
3203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmpi(scratch, Operand::Zero());
3204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (CpuFeatures::IsSupported(ISELECT)) {
3206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(scratch, Operand(thunk_ref));
3207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ isel(eq, scratch, function_address, scratch);
3208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label profiler_disabled;
3210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Label end_profiler_check;
3211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ beq(&profiler_disabled);
3212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(scratch, Operand(thunk_ref));
3213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ b(&end_profiler_check);
3214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&profiler_disabled);
3215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mr(scratch, function_address);
3216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ bind(&end_profiler_check);
3217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate HandleScope in callee-save registers.
3220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r17 - next_address
3221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r14 - next_address->kNextOffset
3222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r15 - next_address->kLimitOffset
3223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // r16 - next_address->kLevelOffset
3224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r17, Operand(next_address));
3225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r14, MemOperand(r17, kNextOffset));
3226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r15, MemOperand(r17, kLimitOffset));
3227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ lwz(r16, MemOperand(r17, kLevelOffset));
3228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ addi(r16, r16, Operand(1));
3229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ stw(r16, MemOperand(r17, kLevelOffset));
3230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_log_timer_events) {
3232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(masm, StackFrame::MANUAL);
3233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ PushSafepointRegisters();
3234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ PrepareCallCFunction(1, r3);
3235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
3236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallCFunction(ExternalReference::log_enter_external_function(isolate),
3237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     1);
3238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ PopSafepointRegisters();
3239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Native call returns to the DirectCEntry stub which redirects to the
3242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // return address pushed on stack (could have moved after GC).
3243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // DirectCEntry stub itself is generated early and never moves.
3244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DirectCEntryStub stub(isolate);
3245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  stub.GenerateCall(masm, scratch);
3246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_log_timer_events) {
3248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FrameScope frame(masm, StackFrame::MANUAL);
3249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ PushSafepointRegisters();
3250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ PrepareCallCFunction(1, r3);
3251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
3252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ CallCFunction(ExternalReference::log_leave_external_function(isolate),
3253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                     1);
3254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ PopSafepointRegisters();
3255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label promote_scheduled_exception;
3258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label delete_allocated_handles;
3259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label leave_exit_frame;
3260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Label return_value_loaded;
3261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // load value from ReturnValue
3263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r3, return_value_operand);
3264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&return_value_loaded);
3265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // No more valid handles (the result handle was the last one). Restore
3266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // previous handle scope.
3267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ StoreP(r14, MemOperand(r17, kNextOffset));
3268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (__ emit_debug_code()) {
3269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lwz(r4, MemOperand(r17, kLevelOffset));
3270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ cmp(r4, r16);
3271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
3272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ subi(r16, r16, Operand(1));
3274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ stw(r16, MemOperand(r17, kLevelOffset));
3275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r0, MemOperand(r17, kLimitOffset));
3276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(r15, r0);
3277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bne(&delete_allocated_handles);
3278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Leave the API exit frame.
3280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&leave_exit_frame);
3281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool restore_context = context_restore_operand != NULL;
3282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (restore_context) {
3283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ LoadP(cp, *context_restore_operand);
3284014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // LeaveExitFrame expects unwind space to be in a register.
3286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (stack_space_operand != NULL) {
3287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ lwz(r14, *stack_space_operand);
3288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
3289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    __ mov(r14, Operand(stack_space));
3290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
3291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL);
3292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Check if the function scheduled an exception.
3294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadRoot(r14, Heap::kTheHoleValueRootIndex);
3295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate)));
3296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ LoadP(r15, MemOperand(r15));
3297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ cmp(r14, r15);
3298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bne(&promote_scheduled_exception);
3299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ blr();
3301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Re-throw by promoting a scheduled exception.
3303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&promote_scheduled_exception);
3304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ TailCallRuntime(Runtime::kPromoteScheduledException);
3305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // HandleScope limit has changed. Delete allocated extensions.
3307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ bind(&delete_allocated_handles);
3308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ StoreP(r15, MemOperand(r17, kLimitOffset));
3309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mr(r14, r3);
3310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ PrepareCallCFunction(1, r15);
3311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
3312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate),
3313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                   1);
3314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mr(r3, r14);
3315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ b(&leave_exit_frame);
3316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
33183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid CallApiCallbackStub::Generate(MacroAssembler* masm) {
3319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // ----------- S t a t e -------------
3320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r3                  : callee
3321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r7                  : call_data
3322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r5                  : holder
3323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- r4                  : api_function_address
3324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- cp                  : context
3325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  --
3326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- sp[0]               : last argument
3327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- ...
3328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- sp[(argc - 1)* 4]   : first argument
3329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //  -- sp[argc * 4]        : receiver
3330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // -----------------------------------
3331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register callee = r3;
3333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register call_data = r7;
3334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register holder = r5;
3335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register api_function_address = r4;
3336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register context = cp;
3337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  typedef FunctionCallbackArguments FCA;
3339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(FCA::kContextSaveIndex == 6);
3341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(FCA::kCalleeIndex == 5);
3342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(FCA::kDataIndex == 4);
3343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
3344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
3345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(FCA::kIsolateIndex == 1);
3346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(FCA::kHolderIndex == 0);
3347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
3348bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(FCA::kArgsLength == 8);
3349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3350bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // new target
3351bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ PushRoot(Heap::kUndefinedValueRootIndex);
3352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // context save
3354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(context);
33553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (!is_lazy()) {
3356109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // load context from callee
3357109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset));
3358109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // callee
3361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(callee);
3362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // call data
3364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(call_data);
3365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Register scratch = call_data;
33673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (!call_data_undefined()) {
3368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
3370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // return value
3371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(scratch);
3372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // return value default
3373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(scratch);
3374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // isolate
3375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate())));
3376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(scratch);
3377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // holder
3378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ push(holder);
3379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Prepare arguments.
3381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ mr(scratch, sp);
3382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Allocate the v8::Arguments structure in the arguments' space since
3384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // it's not controlled by GC.
3385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // PPC LINUX ABI:
3386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //
3387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Create 4 extra slots on stack:
3388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  //    [0] space for DirectCEntryStub's LR save
3389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //    [1-3] FunctionCallbackInfo
3390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  const int kApiStackSpace = 4;
3391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int kFunctionCallbackInfoOffset =
3392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (kStackFrameExtraParamSlot + 1) * kPointerSize;
3393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FrameScope frame_scope(masm, StackFrame::MANUAL);
3395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ EnterExitFrame(false, kApiStackSpace);
3396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!api_function_address.is(r3) && !scratch.is(r3));
3398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // r3 = FunctionCallbackInfo&
3399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Arguments is after the return address.
3400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ addi(r3, sp, Operand(kFunctionCallbackInfoOffset));
3401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // FunctionCallbackInfo::implicit_args_
3402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize));
34033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // FunctionCallbackInfo::values_
34043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc()) * kPointerSize));
34053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
34063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // FunctionCallbackInfo::length_ = argc
34073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ li(ip, Operand(argc()));
34083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ stw(ip, MemOperand(r3, 2 * kPointerSize));
3409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference thunk_ref =
3411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ExternalReference::invoke_function_callback(masm->isolate());
3412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AllowExternalCallThatCantCauseGC scope(masm);
3414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MemOperand context_restore_operand(
3415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
3416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Stores return the first js argument
3417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int return_value_offset = 0;
34183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (is_store()) {
3419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return_value_offset = 2 + FCA::kArgsLength;
3420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
3421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return_value_offset = 2 + FCA::kReturnValueOffset;
3422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
3423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
3424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int stack_space = 0;
3425bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  MemOperand length_operand =
3426bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize);
3427bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  MemOperand* stack_space_operand = &length_operand;
34283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_space = argc() + FCA::kArgsLength + 1;
34293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  stack_space_operand = NULL;
3430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
3431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           stack_space_operand, return_value_operand,
3432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                           &context_restore_operand);
3433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
3434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CallApiGetterStub::Generate(MacroAssembler* masm) {
3437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int arg0Slot = 0;
3438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int accessorInfoSlot = 0;
3439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int apiStackSpace = 0;
3440bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
3441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // name below the exit frame to make GC aware of them.
3442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
3443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
3444bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
3445bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
3446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
3447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
3448bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
3449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
3450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register receiver = ApiGetterDescriptor::ReceiverRegister();
3452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register holder = ApiGetterDescriptor::HolderRegister();
3453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register callback = ApiGetterDescriptor::CallbackRegister();
3454bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register scratch = r7;
3455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(!AreAliased(receiver, holder, callback, scratch));
3456bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3457bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Register api_function_address = r5;
3458bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3459bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ push(receiver);
3460bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Push data from AccessorInfo.
3461bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset));
3462bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ push(scratch);
3463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3464bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Push(scratch, scratch);
3465bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ mov(scratch, Operand(ExternalReference::isolate_address(isolate())));
3466bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ Push(scratch, holder);
3467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Push(Smi::kZero);  // should_throw_on_error -> false
3468bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
3469bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ push(scratch);
3470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // v8::PropertyCallbackInfo::args_ array and name handle.
3472109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
3473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3474109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Load address of v8::PropertyAccessorInfo::args_ array and name handle.
3475109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ mr(r3, sp);                               // r3 = Handle<Name>
3476109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ addi(r4, r3, Operand(1 * kPointerSize));  // r4 = v8::PCI::args_
3477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3478958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// If ABI passes Handles (pointer-sized struct) in a register:
3479958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
3480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Create 2 extra slots on stack:
3481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//    [0] space for DirectCEntryStub's LR save
3482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//    [1] AccessorInfo&
3483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
3484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Otherwise:
3485958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//
3486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Create 3 extra slots on stack:
3487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//    [0] space for DirectCEntryStub's LR save
3488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//    [1] copy of Handle (first arg)
3489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier//    [2] AccessorInfo&
3490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (ABI_PASSES_HANDLES_IN_REGS) {
3491109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    accessorInfoSlot = kStackFrameExtraParamSlot + 1;
3492109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    apiStackSpace = 2;
3493109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  } else {
3494109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    arg0Slot = kStackFrameExtraParamSlot + 1;
3495109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    accessorInfoSlot = arg0Slot + 1;
3496109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    apiStackSpace = 3;
3497109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FrameScope frame_scope(masm, StackFrame::MANUAL);
3500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ EnterExitFrame(false, apiStackSpace);
3501f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
3502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!ABI_PASSES_HANDLES_IN_REGS) {
3503109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // pass 1st arg by reference
3504109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ StoreP(r3, MemOperand(sp, arg0Slot * kPointerSize));
3505109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    __ addi(r3, sp, Operand(arg0Slot * kPointerSize));
3506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
3507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Create v8::PropertyCallbackInfo object on the stack and initialize
3509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // it's args_ field.
3510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ StoreP(r4, MemOperand(sp, accessorInfoSlot * kPointerSize));
3511109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  __ addi(r4, sp, Operand(accessorInfoSlot * kPointerSize));
3512109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // r4 = v8::PropertyCallbackInfo&
3513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ExternalReference thunk_ref =
3515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ExternalReference::invoke_accessor_getter_callback(isolate());
3516109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
3517bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
3518bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  __ LoadP(api_function_address,
3519bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
3520bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
3521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // +3 is to skip prolog, return address and name handle.
3522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MemOperand return_value_operand(
3523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
3524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
3525109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                           kStackUnwindSpace, NULL, return_value_operand, NULL);
3526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
3527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef __
3529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
3530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
3532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif  // V8_TARGET_ARCH_PPC
3533