Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: src/s390/code-stubs-s390.cc

Issue 1725243004: S390: Initial impl of S390 asm, masm, code-stubs,... (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Updated BUILD.gn + cpu-s390.cc to addr @jochen's comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_PPC 5 #if V8_TARGET_ARCH_S390
6 6
7 #include "src/code-stubs.h"
7 #include "src/base/bits.h" 8 #include "src/base/bits.h"
8 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
9 #include "src/code-stubs.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
11 #include "src/ic/handler-compiler.h" 11 #include "src/ic/handler-compiler.h"
12 #include "src/ic/ic.h" 12 #include "src/ic/ic.h"
13 #include "src/ic/stub-cache.h" 13 #include "src/ic/stub-cache.h"
14 #include "src/isolate.h" 14 #include "src/isolate.h"
15 #include "src/ppc/code-stubs-ppc.h"
16 #include "src/regexp/jsregexp.h" 15 #include "src/regexp/jsregexp.h"
17 #include "src/regexp/regexp-macro-assembler.h" 16 #include "src/regexp/regexp-macro-assembler.h"
18 #include "src/runtime/runtime.h" 17 #include "src/runtime/runtime.h"
18 #include "src/s390/code-stubs-s390.h"
19 19
20 namespace v8 { 20 namespace v8 {
21 namespace internal { 21 namespace internal {
22 22
23
24 static void InitializeArrayConstructorDescriptor( 23 static void InitializeArrayConstructorDescriptor(
25 Isolate* isolate, CodeStubDescriptor* descriptor, 24 Isolate* isolate, CodeStubDescriptor* descriptor,
26 int constant_stack_parameter_count) { 25 int constant_stack_parameter_count) {
27 Address deopt_handler = 26 Address deopt_handler =
28 Runtime::FunctionForId(Runtime::kArrayConstructor)->entry; 27 Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
29 28
30 if (constant_stack_parameter_count == 0) { 29 if (constant_stack_parameter_count == 0) {
31 descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 30 descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
32 JS_FUNCTION_STUB_MODE); 31 JS_FUNCTION_STUB_MODE);
33 } else { 32 } else {
34 descriptor->Initialize(r3, deopt_handler, constant_stack_parameter_count, 33 descriptor->Initialize(r2, deopt_handler, constant_stack_parameter_count,
35 JS_FUNCTION_STUB_MODE); 34 JS_FUNCTION_STUB_MODE);
36 } 35 }
37 } 36 }
38 37
39
40 static void InitializeInternalArrayConstructorDescriptor( 38 static void InitializeInternalArrayConstructorDescriptor(
41 Isolate* isolate, CodeStubDescriptor* descriptor, 39 Isolate* isolate, CodeStubDescriptor* descriptor,
42 int constant_stack_parameter_count) { 40 int constant_stack_parameter_count) {
43 Address deopt_handler = 41 Address deopt_handler =
44 Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry; 42 Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
45 43
46 if (constant_stack_parameter_count == 0) { 44 if (constant_stack_parameter_count == 0) {
47 descriptor->Initialize(deopt_handler, constant_stack_parameter_count, 45 descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
48 JS_FUNCTION_STUB_MODE); 46 JS_FUNCTION_STUB_MODE);
49 } else { 47 } else {
50 descriptor->Initialize(r3, deopt_handler, constant_stack_parameter_count, 48 descriptor->Initialize(r2, deopt_handler, constant_stack_parameter_count,
51 JS_FUNCTION_STUB_MODE); 49 JS_FUNCTION_STUB_MODE);
52 } 50 }
53 } 51 }
54 52
55
56 void ArrayNoArgumentConstructorStub::InitializeDescriptor( 53 void ArrayNoArgumentConstructorStub::InitializeDescriptor(
57 CodeStubDescriptor* descriptor) { 54 CodeStubDescriptor* descriptor) {
58 InitializeArrayConstructorDescriptor(isolate(), descriptor, 0); 55 InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
59 } 56 }
60 57
61
62 void ArraySingleArgumentConstructorStub::InitializeDescriptor( 58 void ArraySingleArgumentConstructorStub::InitializeDescriptor(
63 CodeStubDescriptor* descriptor) { 59 CodeStubDescriptor* descriptor) {
64 InitializeArrayConstructorDescriptor(isolate(), descriptor, 1); 60 InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
65 } 61 }
66 62
67
68 void ArrayNArgumentsConstructorStub::InitializeDescriptor( 63 void ArrayNArgumentsConstructorStub::InitializeDescriptor(
69 CodeStubDescriptor* descriptor) { 64 CodeStubDescriptor* descriptor) {
70 InitializeArrayConstructorDescriptor(isolate(), descriptor, -1); 65 InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
71 } 66 }
72 67
73
74 void InternalArrayNoArgumentConstructorStub::InitializeDescriptor( 68 void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
75 CodeStubDescriptor* descriptor) { 69 CodeStubDescriptor* descriptor) {
76 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0); 70 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
77 } 71 }
78 72
79
80 void InternalArraySingleArgumentConstructorStub::InitializeDescriptor( 73 void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
81 CodeStubDescriptor* descriptor) { 74 CodeStubDescriptor* descriptor) {
82 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1); 75 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
83 } 76 }
84 77
85
86 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor( 78 void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
87 CodeStubDescriptor* descriptor) { 79 CodeStubDescriptor* descriptor) {
88 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1); 80 InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
89 } 81 }
90 82
91
92 #define __ ACCESS_MASM(masm) 83 #define __ ACCESS_MASM(masm)
93 84
94 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, 85 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
95 Condition cond); 86 Condition cond);
96 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, 87 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs,
97 Register rhs, Label* lhs_not_nan, 88 Register rhs, Label* lhs_not_nan,
98 Label* slow, bool strict); 89 Label* slow, bool strict);
99 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, 90 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs,
100 Register rhs); 91 Register rhs);
101 92
102
103 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm, 93 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
104 ExternalReference miss) { 94 ExternalReference miss) {
105 // Update the static counter each time a new code stub is generated. 95 // Update the static counter each time a new code stub is generated.
106 isolate()->counters()->code_stubs()->Increment(); 96 isolate()->counters()->code_stubs()->Increment();
107 97
108 CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor(); 98 CallInterfaceDescriptor descriptor = GetCallInterfaceDescriptor();
109 int param_count = descriptor.GetRegisterParameterCount(); 99 int param_count = descriptor.GetRegisterParameterCount();
110 { 100 {
111 // Call the runtime system in a fresh internal frame. 101 // Call the runtime system in a fresh internal frame.
112 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 102 FrameScope scope(masm, StackFrame::INTERNAL);
113 DCHECK(param_count == 0 || 103 DCHECK(param_count == 0 ||
114 r3.is(descriptor.GetRegisterParameter(param_count - 1))); 104 r2.is(descriptor.GetRegisterParameter(param_count - 1)));
115 // Push arguments 105 // Push arguments
116 for (int i = 0; i < param_count; ++i) { 106 for (int i = 0; i < param_count; ++i) {
117 __ push(descriptor.GetRegisterParameter(i)); 107 __ push(descriptor.GetRegisterParameter(i));
118 } 108 }
119 __ CallExternalReference(miss, param_count); 109 __ CallExternalReference(miss, param_count);
120 } 110 }
121 111
122 __ Ret(); 112 __ Ret();
123 } 113 }
124 114
125
126 void DoubleToIStub::Generate(MacroAssembler* masm) { 115 void DoubleToIStub::Generate(MacroAssembler* masm) {
127 Label out_of_range, only_low, negate, done, fastpath_done; 116 Label out_of_range, only_low, negate, done, fastpath_done;
128 Register input_reg = source(); 117 Register input_reg = source();
129 Register result_reg = destination(); 118 Register result_reg = destination();
130 DCHECK(is_truncating()); 119 DCHECK(is_truncating());
131 120
132 int double_offset = offset(); 121 int double_offset = offset();
133 122
134 // Immediate values for this stub fit in instructions, so it's safe to use ip. 123 // Immediate values for this stub fit in instructions, so it's safe to use ip.
135 Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg); 124 Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg);
136 Register scratch_low = 125 Register scratch_low =
137 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch); 126 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
138 Register scratch_high = 127 Register scratch_high =
139 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low); 128 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low);
140 DoubleRegister double_scratch = kScratchDoubleReg; 129 DoubleRegister double_scratch = kScratchDoubleReg;
141 130
142 __ push(scratch); 131 __ push(scratch);
143 // Account for saved regs if input is sp. 132 // Account for saved regs if input is sp.
144 if (input_reg.is(sp)) double_offset += kPointerSize; 133 if (input_reg.is(sp)) double_offset += kPointerSize;
145 134
146 if (!skip_fastpath()) { 135 if (!skip_fastpath()) {
147 // Load double input. 136 // Load double input.
148 __ lfd(double_scratch, MemOperand(input_reg, double_offset)); 137 __ LoadDouble(double_scratch, MemOperand(input_reg, double_offset));
149 138
150 // Do fast-path convert from double to int. 139 // Do fast-path convert from double to int.
151 __ ConvertDoubleToInt64(double_scratch, 140 __ ConvertDoubleToInt64(double_scratch,
152 #if !V8_TARGET_ARCH_PPC64 141 #if !V8_TARGET_ARCH_S390X
153 scratch, 142 scratch,
154 #endif 143 #endif
155 result_reg, d0); 144 result_reg, d0);
156 145
157 // Test for overflow 146 // Test for overflow
158 #if V8_TARGET_ARCH_PPC64 147 #if V8_TARGET_ARCH_S390X
159 __ TestIfInt32(result_reg, r0); 148 __ TestIfInt32(result_reg, r0);
160 #else 149 #else
161 __ TestIfInt32(scratch, result_reg, r0); 150 __ TestIfInt32(scratch, result_reg, r0);
162 #endif 151 #endif
163 __ beq(&fastpath_done); 152 __ beq(&fastpath_done, Label::kNear);
164 } 153 }
165 154
166 __ Push(scratch_high, scratch_low); 155 __ Push(scratch_high, scratch_low);
167 // Account for saved regs if input is sp. 156 // Account for saved regs if input is sp.
168 if (input_reg.is(sp)) double_offset += 2 * kPointerSize; 157 if (input_reg.is(sp)) double_offset += 2 * kPointerSize;
169 158
170 __ lwz(scratch_high, 159 __ LoadlW(scratch_high,
171 MemOperand(input_reg, double_offset + Register::kExponentOffset)); 160 MemOperand(input_reg, double_offset + Register::kExponentOffset));
172 __ lwz(scratch_low, 161 __ LoadlW(scratch_low,
173 MemOperand(input_reg, double_offset + Register::kMantissaOffset)); 162 MemOperand(input_reg, double_offset + Register::kMantissaOffset));
174 163
175 __ ExtractBitMask(scratch, scratch_high, HeapNumber::kExponentMask); 164 __ ExtractBitMask(scratch, scratch_high, HeapNumber::kExponentMask);
176 // Load scratch with exponent - 1. This is faster than loading 165 // Load scratch with exponent - 1. This is faster than loading
177 // with exponent because Bias + 1 = 1024 which is a *PPC* immediate value. 166 // with exponent because Bias + 1 = 1024 which is a *S390* immediate value.
178 STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024); 167 STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024);
179 __ subi(scratch, scratch, Operand(HeapNumber::kExponentBias + 1)); 168 __ SubP(scratch, Operand(HeapNumber::kExponentBias + 1));
180 // If exponent is greater than or equal to 84, the 32 less significant 169 // If exponent is greater than or equal to 84, the 32 less significant
181 // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits), 170 // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
182 // the result is 0. 171 // the result is 0.
183 // Compare exponent with 84 (compare exponent - 1 with 83). 172 // Compare exponent with 84 (compare exponent - 1 with 83).
184 __ cmpi(scratch, Operand(83)); 173 __ CmpP(scratch, Operand(83));
185 __ bge(&out_of_range); 174 __ bge(&out_of_range, Label::kNear);
186 175
187 // If we reach this code, 31 <= exponent <= 83. 176 // If we reach this code, 31 <= exponent <= 83.
188 // So, we don't have to handle cases where 0 <= exponent <= 20 for 177 // So, we don't have to handle cases where 0 <= exponent <= 20 for
189 // which we would need to shift right the high part of the mantissa. 178 // which we would need to shift right the high part of the mantissa.
190 // Scratch contains exponent - 1. 179 // Scratch contains exponent - 1.
191 // Load scratch with 52 - exponent (load with 51 - (exponent - 1)). 180 // Load scratch with 52 - exponent (load with 51 - (exponent - 1)).
192 __ subfic(scratch, scratch, Operand(51)); 181 __ Load(r0, Operand(51));
193 __ cmpi(scratch, Operand::Zero()); 182 __ SubP(scratch, r0, scratch);
194 __ ble(&only_low); 183 __ CmpP(scratch, Operand::Zero());
184 __ ble(&only_low, Label::kNear);
195 // 21 <= exponent <= 51, shift scratch_low and scratch_high 185 // 21 <= exponent <= 51, shift scratch_low and scratch_high
196 // to generate the result. 186 // to generate the result.
197 __ srw(scratch_low, scratch_low, scratch); 187 __ ShiftRight(scratch_low, scratch_low, scratch);
198 // Scratch contains: 52 - exponent. 188 // Scratch contains: 52 - exponent.
199 // We needs: exponent - 20. 189 // We needs: exponent - 20.
200 // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20. 190 // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20.
201 __ subfic(scratch, scratch, Operand(32)); 191 __ Load(r0, Operand(32));
192 __ SubP(scratch, r0, scratch);
202 __ ExtractBitMask(result_reg, scratch_high, HeapNumber::kMantissaMask); 193 __ ExtractBitMask(result_reg, scratch_high, HeapNumber::kMantissaMask);
203 // Set the implicit 1 before the mantissa part in scratch_high. 194 // Set the implicit 1 before the mantissa part in scratch_high.
204 STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord >= 16); 195 STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord >= 16);
205 __ oris(result_reg, result_reg, 196 __ Load(r0, Operand(1 << ((HeapNumber::kMantissaBitsInTopWord)-16)));
206 Operand(1 << ((HeapNumber::kMantissaBitsInTopWord) - 16))); 197 __ ShiftLeftP(r0, r0, Operand(16));
207 __ slw(r0, result_reg, scratch); 198 __ OrP(result_reg, result_reg, r0);
208 __ orx(result_reg, scratch_low, r0); 199 __ ShiftLeft(r0, result_reg, scratch);
209 __ b(&negate); 200 __ OrP(result_reg, scratch_low, r0);
201 __ b(&negate, Label::kNear);
210 202
211 __ bind(&out_of_range); 203 __ bind(&out_of_range);
212 __ mov(result_reg, Operand::Zero()); 204 __ mov(result_reg, Operand::Zero());
213 __ b(&done); 205 __ b(&done, Label::kNear);
214 206
215 __ bind(&only_low); 207 __ bind(&only_low);
216 // 52 <= exponent <= 83, shift only scratch_low. 208 // 52 <= exponent <= 83, shift only scratch_low.
217 // On entry, scratch contains: 52 - exponent. 209 // On entry, scratch contains: 52 - exponent.
218 __ neg(scratch, scratch); 210 __ LoadComplementRR(scratch, scratch);
219 __ slw(result_reg, scratch_low, scratch); 211 __ ShiftLeft(result_reg, scratch_low, scratch);
220 212
221 __ bind(&negate); 213 __ bind(&negate);
222 // If input was positive, scratch_high ASR 31 equals 0 and 214 // If input was positive, scratch_high ASR 31 equals 0 and
223 // scratch_high LSR 31 equals zero. 215 // scratch_high LSR 31 equals zero.
224 // New result = (result eor 0) + 0 = result. 216 // New result = (result eor 0) + 0 = result.
225 // If the input was negative, we have to negate the result. 217 // If the input was negative, we have to negate the result.
226 // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1. 218 // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1.
227 // New result = (result eor 0xffffffff) + 1 = 0 - result. 219 // New result = (result eor 0xffffffff) + 1 = 0 - result.
228 __ srawi(r0, scratch_high, 31); 220 __ ShiftRightArith(r0, scratch_high, Operand(31));
229 #if V8_TARGET_ARCH_PPC64 221 #if V8_TARGET_ARCH_S390X
230 __ srdi(r0, r0, Operand(32)); 222 __ lgfr(r0, r0);
223 __ ShiftRightP(r0, r0, Operand(32));
231 #endif 224 #endif
232 __ xor_(result_reg, result_reg, r0); 225 __ XorP(result_reg, r0);
233 __ srwi(r0, scratch_high, Operand(31)); 226 __ ShiftRight(r0, scratch_high, Operand(31));
234 __ add(result_reg, result_reg, r0); 227 __ AddP(result_reg, r0);
235 228
236 __ bind(&done); 229 __ bind(&done);
237 __ Pop(scratch_high, scratch_low); 230 __ Pop(scratch_high, scratch_low);
238 231
239 __ bind(&fastpath_done); 232 __ bind(&fastpath_done);
240 __ pop(scratch); 233 __ pop(scratch);
241 234
242 __ Ret(); 235 __ Ret();
243 } 236 }
244 237
245
246 // Handle the case where the lhs and rhs are the same object. 238 // Handle the case where the lhs and rhs are the same object.
247 // Equality is almost reflexive (everything but NaN), so this is a test 239 // Equality is almost reflexive (everything but NaN), so this is a test
248 // for "identity and not NaN". 240 // for "identity and not NaN".
249 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow, 241 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
250 Condition cond) { 242 Condition cond) {
251 Label not_identical; 243 Label not_identical;
252 Label heap_number, return_equal; 244 Label heap_number, return_equal;
253 __ cmp(r3, r4); 245 __ CmpP(r2, r3);
254 __ bne(&not_identical); 246 __ bne(&not_identical);
255 247
256 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 248 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
257 // so we do the second best thing - test it ourselves. 249 // so we do the second best thing - test it ourselves.
258 // They are both equal and they are not both Smis so both of them are not 250 // They are both equal and they are not both Smis so both of them are not
259 // Smis. If it's not a heap number, then return equal. 251 // Smis. If it's not a heap number, then return equal.
260 if (cond == lt || cond == gt) { 252 if (cond == lt || cond == gt) {
261 // Call runtime on identical JSObjects. 253 // Call runtime on identical JSObjects.
262 __ CompareObjectType(r3, r7, r7, FIRST_JS_RECEIVER_TYPE); 254 __ CompareObjectType(r2, r6, r6, FIRST_JS_RECEIVER_TYPE);
263 __ bge(slow); 255 __ bge(slow);
264 // Call runtime on identical symbols since we need to throw a TypeError. 256 // Call runtime on identical symbols since we need to throw a TypeError.
265 __ cmpi(r7, Operand(SYMBOL_TYPE)); 257 __ CmpP(r6, Operand(SYMBOL_TYPE));
266 __ beq(slow); 258 __ beq(slow);
267 // Call runtime on identical SIMD values since we must throw a TypeError. 259 // Call runtime on identical SIMD values since we must throw a TypeError.
268 __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); 260 __ CmpP(r6, Operand(SIMD128_VALUE_TYPE));
269 __ beq(slow); 261 __ beq(slow);
270 } else { 262 } else {
271 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); 263 __ CompareObjectType(r2, r6, r6, HEAP_NUMBER_TYPE);
272 __ beq(&heap_number); 264 __ beq(&heap_number);
273 // Comparing JS objects with <=, >= is complicated. 265 // Comparing JS objects with <=, >= is complicated.
274 if (cond != eq) { 266 if (cond != eq) {
275 __ cmpi(r7, Operand(FIRST_JS_RECEIVER_TYPE)); 267 __ CmpP(r6, Operand(FIRST_JS_RECEIVER_TYPE));
276 __ bge(slow); 268 __ bge(slow);
277 // Call runtime on identical symbols since we need to throw a TypeError. 269 // Call runtime on identical symbols since we need to throw a TypeError.
278 __ cmpi(r7, Operand(SYMBOL_TYPE)); 270 __ CmpP(r6, Operand(SYMBOL_TYPE));
279 __ beq(slow); 271 __ beq(slow);
280 // Call runtime on identical SIMD values since we must throw a TypeError. 272 // Call runtime on identical SIMD values since we must throw a TypeError.
281 __ cmpi(r7, Operand(SIMD128_VALUE_TYPE)); 273 __ CmpP(r6, Operand(SIMD128_VALUE_TYPE));
282 __ beq(slow); 274 __ beq(slow);
283 // Normally here we fall through to return_equal, but undefined is 275 // Normally here we fall through to return_equal, but undefined is
284 // special: (undefined == undefined) == true, but 276 // special: (undefined == undefined) == true, but
285 // (undefined <= undefined) == false! See ECMAScript 11.8.5. 277 // (undefined <= undefined) == false! See ECMAScript 11.8.5.
286 if (cond == le || cond == ge) { 278 if (cond == le || cond == ge) {
287 __ cmpi(r7, Operand(ODDBALL_TYPE)); 279 __ CmpP(r6, Operand(ODDBALL_TYPE));
288 __ bne(&return_equal); 280 __ bne(&return_equal);
289 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); 281 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
290 __ cmp(r3, r5);
291 __ bne(&return_equal); 282 __ bne(&return_equal);
292 if (cond == le) { 283 if (cond == le) {
293 // undefined <= undefined should fail. 284 // undefined <= undefined should fail.
294 __ li(r3, Operand(GREATER)); 285 __ LoadImmP(r2, Operand(GREATER));
295 } else { 286 } else {
296 // undefined >= undefined should fail. 287 // undefined >= undefined should fail.
297 __ li(r3, Operand(LESS)); 288 __ LoadImmP(r2, Operand(LESS));
298 } 289 }
299 __ Ret(); 290 __ Ret();
300 } 291 }
301 } 292 }
302 } 293 }
303 294
304 __ bind(&return_equal); 295 __ bind(&return_equal);
305 if (cond == lt) { 296 if (cond == lt) {
306 __ li(r3, Operand(GREATER)); // Things aren't less than themselves. 297 __ LoadImmP(r2, Operand(GREATER)); // Things aren't less than themselves.
307 } else if (cond == gt) { 298 } else if (cond == gt) {
308 __ li(r3, Operand(LESS)); // Things aren't greater than themselves. 299 __ LoadImmP(r2, Operand(LESS)); // Things aren't greater than themselves.
309 } else { 300 } else {
310 __ li(r3, Operand(EQUAL)); // Things are <=, >=, ==, === themselves. 301 __ LoadImmP(r2, Operand(EQUAL)); // Things are <=, >=, ==, === themselves
311 } 302 }
312 __ Ret(); 303 __ Ret();
313 304
314 // For less and greater we don't have to check for NaN since the result of 305 // For less and greater we don't have to check for NaN since the result of
315 // x < x is false regardless. For the others here is some code to check 306 // x < x is false regardless. For the others here is some code to check
316 // for NaN. 307 // for NaN.
317 if (cond != lt && cond != gt) { 308 if (cond != lt && cond != gt) {
318 __ bind(&heap_number); 309 __ bind(&heap_number);
319 // It is a heap number, so return non-equal if it's NaN and equal if it's 310 // It is a heap number, so return non-equal if it's NaN and equal if it's
320 // not NaN. 311 // not NaN.
321 312
322 // The representation of NaN values has all exponent bits (52..62) set, 313 // The representation of NaN values has all exponent bits (52..62) set,
323 // and not all mantissa bits (0..51) clear. 314 // and not all mantissa bits (0..51) clear.
324 // Read top bits of double representation (second word of value). 315 // Read top bits of double representation (second word of value).
325 __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset)); 316 __ LoadlW(r4, FieldMemOperand(r2, HeapNumber::kExponentOffset));
326 // Test that exponent bits are all set. 317 // Test that exponent bits are all set.
327 STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u); 318 STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u);
328 __ ExtractBitMask(r6, r5, HeapNumber::kExponentMask); 319 __ ExtractBitMask(r5, r4, HeapNumber::kExponentMask);
329 __ cmpli(r6, Operand(0x7ff)); 320 __ CmpLogicalP(r5, Operand(0x7ff));
330 __ bne(&return_equal); 321 __ bne(&return_equal);
331 322
332 // Shift out flag and all exponent bits, retaining only mantissa. 323 // Shift out flag and all exponent bits, retaining only mantissa.
333 __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord)); 324 __ sll(r4, Operand(HeapNumber::kNonMantissaBitsInTopWord));
334 // Or with all low-bits of mantissa. 325 // Or with all low-bits of mantissa.
335 __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); 326 __ LoadlW(r5, FieldMemOperand(r2, HeapNumber::kMantissaOffset));
336 __ orx(r3, r6, r5); 327 __ OrP(r2, r5, r4);
337 __ cmpi(r3, Operand::Zero()); 328 __ CmpP(r2, Operand::Zero());
338 // For equal we already have the right value in r3: Return zero (equal) 329 // For equal we already have the right value in r2: Return zero (equal)
339 // if all bits in mantissa are zero (it's an Infinity) and non-zero if 330 // if all bits in mantissa are zero (it's an Infinity) and non-zero if
340 // not (it's a NaN). For <= and >= we need to load r0 with the failing 331 // not (it's a NaN). For <= and >= we need to load r0 with the failing
341 // value if it's a NaN. 332 // value if it's a NaN.
342 if (cond != eq) { 333 if (cond != eq) {
343 if (CpuFeatures::IsSupported(ISELECT)) { 334 Label not_equal;
344 __ li(r4, Operand((cond == le) ? GREATER : LESS)); 335 __ bne(&not_equal, Label::kNear);
345 __ isel(eq, r3, r3, r4); 336 // All-zero means Infinity means equal.
337 __ Ret();
338 __ bind(&not_equal);
339 if (cond == le) {
340 __ LoadImmP(r2, Operand(GREATER)); // NaN <= NaN should fail.
346 } else { 341 } else {
347 // All-zero means Infinity means equal. 342 __ LoadImmP(r2, Operand(LESS)); // NaN >= NaN should fail.
348 __ Ret(eq);
349 if (cond == le) {
350 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail.
351 } else {
352 __ li(r3, Operand(LESS)); // NaN >= NaN should fail.
353 }
354 } 343 }
355 } 344 }
356 __ Ret(); 345 __ Ret();
357 } 346 }
358 // No fall through here. 347 // No fall through here.
359 348
360 __ bind(&not_identical); 349 __ bind(&not_identical);
361 } 350 }
362 351
363
364 // See comment at call site. 352 // See comment at call site.
365 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs, 353 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs,
366 Register rhs, Label* lhs_not_nan, 354 Register rhs, Label* lhs_not_nan,
367 Label* slow, bool strict) { 355 Label* slow, bool strict) {
368 DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 356 DCHECK((lhs.is(r2) && rhs.is(r3)) || (lhs.is(r3) && rhs.is(r2)));
369 357
370 Label rhs_is_smi; 358 Label rhs_is_smi;
371 __ JumpIfSmi(rhs, &rhs_is_smi); 359 __ JumpIfSmi(rhs, &rhs_is_smi);
372 360
373 // Lhs is a Smi. Check whether the rhs is a heap number. 361 // Lhs is a Smi. Check whether the rhs is a heap number.
374 __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE); 362 __ CompareObjectType(rhs, r5, r6, HEAP_NUMBER_TYPE);
375 if (strict) { 363 if (strict) {
376 // If rhs is not a number and lhs is a Smi then strict equality cannot 364 // If rhs is not a number and lhs is a Smi then strict equality cannot
377 // succeed. Return non-equal 365 // succeed. Return non-equal
378 // If rhs is r3 then there is already a non zero value in it. 366 // If rhs is r2 then there is already a non zero value in it.
379 if (!rhs.is(r3)) { 367 Label skip;
380 Label skip; 368 __ beq(&skip, Label::kNear);
381 __ beq(&skip); 369 if (!rhs.is(r2)) {
382 __ mov(r3, Operand(NOT_EQUAL)); 370 __ mov(r2, Operand(NOT_EQUAL));
383 __ Ret();
384 __ bind(&skip);
385 } else {
386 __ Ret(ne);
387 } 371 }
372 __ Ret();
373 __ bind(&skip);
388 } else { 374 } else {
389 // Smi compared non-strictly with a non-Smi non-heap-number. Call 375 // Smi compared non-strictly with a non-Smi non-heap-number. Call
390 // the runtime. 376 // the runtime.
391 __ bne(slow); 377 __ bne(slow);
392 } 378 }
393 379
394 // Lhs is a smi, rhs is a number. 380 // Lhs is a smi, rhs is a number.
395 // Convert lhs to a double in d7. 381 // Convert lhs to a double in d7.
396 __ SmiToDouble(d7, lhs); 382 __ SmiToDouble(d7, lhs);
397 // Load the double from rhs, tagged HeapNumber r3, to d6. 383 // Load the double from rhs, tagged HeapNumber r2, to d6.
398 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 384 __ LoadDouble(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
399 385
400 // We now have both loaded as doubles but we can skip the lhs nan check 386 // We now have both loaded as doubles but we can skip the lhs nan check
401 // since it's a smi. 387 // since it's a smi.
402 __ b(lhs_not_nan); 388 __ b(lhs_not_nan);
403 389
404 __ bind(&rhs_is_smi); 390 __ bind(&rhs_is_smi);
405 // Rhs is a smi. Check whether the non-smi lhs is a heap number. 391 // Rhs is a smi. Check whether the non-smi lhs is a heap number.
406 __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE); 392 __ CompareObjectType(lhs, r6, r6, HEAP_NUMBER_TYPE);
407 if (strict) { 393 if (strict) {
408 // If lhs is not a number and rhs is a smi then strict equality cannot 394 // If lhs is not a number and rhs is a smi then strict equality cannot
409 // succeed. Return non-equal. 395 // succeed. Return non-equal.
410 // If lhs is r3 then there is already a non zero value in it. 396 // If lhs is r2 then there is already a non zero value in it.
411 if (!lhs.is(r3)) { 397 Label skip;
412 Label skip; 398 __ beq(&skip, Label::kNear);
413 __ beq(&skip); 399 if (!lhs.is(r2)) {
414 __ mov(r3, Operand(NOT_EQUAL)); 400 __ mov(r2, Operand(NOT_EQUAL));
415 __ Ret();
416 __ bind(&skip);
417 } else {
418 __ Ret(ne);
419 } 401 }
402 __ Ret();
403 __ bind(&skip);
420 } else { 404 } else {
421 // Smi compared non-strictly with a non-smi non-heap-number. Call 405 // Smi compared non-strictly with a non-smi non-heap-number. Call
422 // the runtime. 406 // the runtime.
423 __ bne(slow); 407 __ bne(slow);
424 } 408 }
425 409
426 // Rhs is a smi, lhs is a heap number. 410 // Rhs is a smi, lhs is a heap number.
427 // Load the double from lhs, tagged HeapNumber r4, to d7. 411 // Load the double from lhs, tagged HeapNumber r3, to d7.
428 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 412 __ LoadDouble(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
429 // Convert rhs to a double in d6. 413 // Convert rhs to a double in d6.
430 __ SmiToDouble(d6, rhs); 414 __ SmiToDouble(d6, rhs);
431 // Fall through to both_loaded_as_doubles. 415 // Fall through to both_loaded_as_doubles.
432 } 416 }
433 417
434
435 // See comment at call site. 418 // See comment at call site.
436 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs, 419 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, Register lhs,
437 Register rhs) { 420 Register rhs) {
438 DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 421 DCHECK((lhs.is(r2) && rhs.is(r3)) || (lhs.is(r3) && rhs.is(r2)));
439 422
440 // If either operand is a JS object or an oddball value, then they are 423 // If either operand is a JS object or an oddball value, then they are
441 // not equal since their pointers are different. 424 // not equal since their pointers are different.
442 // There is no test for undetectability in strict equality. 425 // There is no test for undetectability in strict equality.
443 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 426 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
444 Label first_non_object; 427 Label first_non_object;
445 // Get the type of the first operand into r5 and compare it with 428 // Get the type of the first operand into r4 and compare it with
446 // FIRST_JS_RECEIVER_TYPE. 429 // FIRST_JS_RECEIVER_TYPE.
447 __ CompareObjectType(rhs, r5, r5, FIRST_JS_RECEIVER_TYPE); 430 __ CompareObjectType(rhs, r4, r4, FIRST_JS_RECEIVER_TYPE);
448 __ blt(&first_non_object); 431 __ blt(&first_non_object, Label::kNear);
449 432
450 // Return non-zero (r3 is not zero) 433 // Return non-zero (r2 is not zero)
451 Label return_not_equal; 434 Label return_not_equal;
452 __ bind(&return_not_equal); 435 __ bind(&return_not_equal);
453 __ Ret(); 436 __ Ret();
454 437
455 __ bind(&first_non_object); 438 __ bind(&first_non_object);
456 // Check for oddballs: true, false, null, undefined. 439 // Check for oddballs: true, false, null, undefined.
457 __ cmpi(r5, Operand(ODDBALL_TYPE)); 440 __ CmpP(r4, Operand(ODDBALL_TYPE));
458 __ beq(&return_not_equal); 441 __ beq(&return_not_equal);
459 442
460 __ CompareObjectType(lhs, r6, r6, FIRST_JS_RECEIVER_TYPE); 443 __ CompareObjectType(lhs, r5, r5, FIRST_JS_RECEIVER_TYPE);
461 __ bge(&return_not_equal); 444 __ bge(&return_not_equal);
462 445
463 // Check for oddballs: true, false, null, undefined. 446 // Check for oddballs: true, false, null, undefined.
464 __ cmpi(r6, Operand(ODDBALL_TYPE)); 447 __ CmpP(r5, Operand(ODDBALL_TYPE));
465 __ beq(&return_not_equal); 448 __ beq(&return_not_equal);
466 449
467 // Now that we have the types we might as well check for 450 // Now that we have the types we might as well check for
468 // internalized-internalized. 451 // internalized-internalized.
469 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 452 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
470 __ orx(r5, r5, r6); 453 __ OrP(r4, r4, r5);
471 __ andi(r0, r5, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 454 __ AndP(r0, r4, Operand(kIsNotStringMask | kIsNotInternalizedMask));
472 __ beq(&return_not_equal, cr0); 455 __ beq(&return_not_equal);
473 } 456 }
474 457
475
476 // See comment at call site. 458 // See comment at call site.
477 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, Register lhs, 459 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, Register lhs,
478 Register rhs, 460 Register rhs,
479 Label* both_loaded_as_doubles, 461 Label* both_loaded_as_doubles,
480 Label* not_heap_numbers, Label* slow) { 462 Label* not_heap_numbers, Label* slow) {
481 DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 463 DCHECK((lhs.is(r2) && rhs.is(r3)) || (lhs.is(r3) && rhs.is(r2)));
482 464
483 __ CompareObjectType(rhs, r6, r5, HEAP_NUMBER_TYPE); 465 __ CompareObjectType(rhs, r5, r4, HEAP_NUMBER_TYPE);
484 __ bne(not_heap_numbers); 466 __ bne(not_heap_numbers);
485 __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset)); 467 __ LoadP(r4, FieldMemOperand(lhs, HeapObject::kMapOffset));
486 __ cmp(r5, r6); 468 __ CmpP(r4, r5);
487 __ bne(slow); // First was a heap number, second wasn't. Go slow case. 469 __ bne(slow); // First was a heap number, second wasn't. Go slow case.
488 470
489 // Both are heap numbers. Load them up then jump to the code we have 471 // Both are heap numbers. Load them up then jump to the code we have
490 // for that. 472 // for that.
491 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); 473 __ LoadDouble(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
492 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); 474 __ LoadDouble(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
493 475
494 __ b(both_loaded_as_doubles); 476 __ b(both_loaded_as_doubles);
495 } 477 }
496 478
497
498 // Fast negative check for internalized-to-internalized equality. 479 // Fast negative check for internalized-to-internalized equality.
499 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 480 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
500 Register lhs, Register rhs, 481 Register lhs, Register rhs,
501 Label* possible_strings, 482 Label* possible_strings,
502 Label* runtime_call) { 483 Label* runtime_call) {
503 DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3))); 484 DCHECK((lhs.is(r2) && rhs.is(r3)) || (lhs.is(r3) && rhs.is(r2)));
504 485
505 // r5 is object type of rhs. 486 // r4 is object type of rhs.
506 Label object_test, return_unequal, undetectable; 487 Label object_test, return_unequal, undetectable;
507 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 488 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
508 __ andi(r0, r5, Operand(kIsNotStringMask)); 489 __ mov(r0, Operand(kIsNotStringMask));
509 __ bne(&object_test, cr0); 490 __ AndP(r0, r4);
510 __ andi(r0, r5, Operand(kIsNotInternalizedMask)); 491 __ bne(&object_test, Label::kNear);
511 __ bne(possible_strings, cr0); 492 __ mov(r0, Operand(kIsNotInternalizedMask));
512 __ CompareObjectType(lhs, r6, r6, FIRST_NONSTRING_TYPE); 493 __ AndP(r0, r4);
494 __ bne(possible_strings);
495 __ CompareObjectType(lhs, r5, r5, FIRST_NONSTRING_TYPE);
513 __ bge(runtime_call); 496 __ bge(runtime_call);
514 __ andi(r0, r6, Operand(kIsNotInternalizedMask)); 497 __ mov(r0, Operand(kIsNotInternalizedMask));
515 __ bne(possible_strings, cr0); 498 __ AndP(r0, r5);
499 __ bne(possible_strings);
516 500
517 // Both are internalized. We already checked they weren't the same pointer so 501 // Both are internalized. We already checked they weren't the same pointer so
518 // they are not equal. Return non-equal by returning the non-zero object 502 // they are not equal. Return non-equal by returning the non-zero object
519 // pointer in r3. 503 // pointer in r2.
520 __ Ret(); 504 __ Ret();
521 505
522 __ bind(&object_test); 506 __ bind(&object_test);
523 __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset)); 507 __ LoadP(r4, FieldMemOperand(lhs, HeapObject::kMapOffset));
524 __ LoadP(r6, FieldMemOperand(rhs, HeapObject::kMapOffset)); 508 __ LoadP(r5, FieldMemOperand(rhs, HeapObject::kMapOffset));
525 __ lbz(r7, FieldMemOperand(r5, Map::kBitFieldOffset)); 509 __ LoadlB(r6, FieldMemOperand(r4, Map::kBitFieldOffset));
526 __ lbz(r8, FieldMemOperand(r6, Map::kBitFieldOffset)); 510 __ LoadlB(r7, FieldMemOperand(r5, Map::kBitFieldOffset));
527 __ andi(r0, r7, Operand(1 << Map::kIsUndetectable)); 511 __ AndP(r0, r6, Operand(1 << Map::kIsUndetectable));
528 __ bne(&undetectable, cr0); 512 __ bne(&undetectable);
529 __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); 513 __ AndP(r0, r7, Operand(1 << Map::kIsUndetectable));
530 __ bne(&return_unequal, cr0); 514 __ bne(&return_unequal);
531 515
516 __ CompareInstanceType(r4, r4, FIRST_JS_RECEIVER_TYPE);
517 __ blt(runtime_call);
532 __ CompareInstanceType(r5, r5, FIRST_JS_RECEIVER_TYPE); 518 __ CompareInstanceType(r5, r5, FIRST_JS_RECEIVER_TYPE);
533 __ blt(runtime_call); 519 __ blt(runtime_call);
534 __ CompareInstanceType(r6, r6, FIRST_JS_RECEIVER_TYPE);
535 __ blt(runtime_call);
536 520
537 __ bind(&return_unequal); 521 __ bind(&return_unequal);
538 // Return non-equal by returning the non-zero object pointer in r3. 522 // Return non-equal by returning the non-zero object pointer in r2.
539 __ Ret(); 523 __ Ret();
540 524
541 __ bind(&undetectable); 525 __ bind(&undetectable);
542 __ andi(r0, r8, Operand(1 << Map::kIsUndetectable)); 526 __ AndP(r0, r7, Operand(1 << Map::kIsUndetectable));
543 __ beq(&return_unequal, cr0); 527 __ beq(&return_unequal);
544 __ li(r3, Operand(EQUAL)); 528 __ LoadImmP(r2, Operand(EQUAL));
545 __ Ret(); 529 __ Ret();
546 } 530 }
547 531
548
549 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input, 532 static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input,
550 Register scratch, 533 Register scratch,
551 CompareICState::State expected, 534 CompareICState::State expected,
552 Label* fail) { 535 Label* fail) {
553 Label ok; 536 Label ok;
554 if (expected == CompareICState::SMI) { 537 if (expected == CompareICState::SMI) {
555 __ JumpIfNotSmi(input, fail); 538 __ JumpIfNotSmi(input, fail);
556 } else if (expected == CompareICState::NUMBER) { 539 } else if (expected == CompareICState::NUMBER) {
557 __ JumpIfSmi(input, &ok); 540 __ JumpIfSmi(input, &ok);
558 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, 541 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
559 DONT_DO_SMI_CHECK); 542 DONT_DO_SMI_CHECK);
560 } 543 }
561 // We could be strict about internalized/non-internalized here, but as long as 544 // We could be strict about internalized/non-internalized here, but as long as
562 // hydrogen doesn't care, the stub doesn't have to care either. 545 // hydrogen doesn't care, the stub doesn't have to care either.
563 __ bind(&ok); 546 __ bind(&ok);
564 } 547 }
565 548
566 549 // On entry r3 and r4 are the values to be compared.
567 // On entry r4 and r5 are the values to be compared. 550 // On exit r2 is 0, positive or negative to indicate the result of
568 // On exit r3 is 0, positive or negative to indicate the result of
569 // the comparison. 551 // the comparison.
570 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { 552 void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
571 Register lhs = r4; 553 Register lhs = r3;
572 Register rhs = r3; 554 Register rhs = r2;
573 Condition cc = GetCondition(); 555 Condition cc = GetCondition();
574 556
575 Label miss; 557 Label miss;
576 CompareICStub_CheckInputType(masm, lhs, r5, left(), &miss); 558 CompareICStub_CheckInputType(masm, lhs, r4, left(), &miss);
577 CompareICStub_CheckInputType(masm, rhs, r6, right(), &miss); 559 CompareICStub_CheckInputType(masm, rhs, r5, right(), &miss);
578 560
579 Label slow; // Call builtin. 561 Label slow; // Call builtin.
580 Label not_smis, both_loaded_as_doubles, lhs_not_nan; 562 Label not_smis, both_loaded_as_doubles, lhs_not_nan;
581 563
582 Label not_two_smis, smi_done; 564 Label not_two_smis, smi_done;
583 __ orx(r5, r4, r3); 565 __ OrP(r4, r3, r2);
584 __ JumpIfNotSmi(r5, &not_two_smis); 566 __ JumpIfNotSmi(r4, &not_two_smis);
585 __ SmiUntag(r4);
586 __ SmiUntag(r3); 567 __ SmiUntag(r3);
587 __ sub(r3, r4, r3); 568 __ SmiUntag(r2);
569 __ SubP(r2, r3, r2);
588 __ Ret(); 570 __ Ret();
589 __ bind(&not_two_smis); 571 __ bind(&not_two_smis);
590 572
591 // NOTICE! This code is only reached after a smi-fast-case check, so 573 // NOTICE! This code is only reached after a smi-fast-case check, so
592 // it is certain that at least one operand isn't a smi. 574 // it is certain that at least one operand isn't a smi.
593 575
594 // Handle the case where the objects are identical. Either returns the answer 576 // Handle the case where the objects are identical. Either returns the answer
595 // or goes to slow. Only falls through if the objects were not identical. 577 // or goes to slow. Only falls through if the objects were not identical.
596 EmitIdenticalObjectComparison(masm, &slow, cc); 578 EmitIdenticalObjectComparison(masm, &slow, cc);
597 579
598 // If either is a Smi (we know that not both are), then they can only 580 // If either is a Smi (we know that not both are), then they can only
599 // be strictly equal if the other is a HeapNumber. 581 // be strictly equal if the other is a HeapNumber.
600 STATIC_ASSERT(kSmiTag == 0); 582 STATIC_ASSERT(kSmiTag == 0);
601 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0)); 583 DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
602 __ and_(r5, lhs, rhs); 584 __ AndP(r4, lhs, rhs);
603 __ JumpIfNotSmi(r5, &not_smis); 585 __ JumpIfNotSmi(r4, &not_smis);
604 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 586 // One operand is a smi. EmitSmiNonsmiComparison generates code that can:
605 // 1) Return the answer. 587 // 1) Return the answer.
606 // 2) Go to slow. 588 // 2) Go to slow.
607 // 3) Fall through to both_loaded_as_doubles. 589 // 3) Fall through to both_loaded_as_doubles.
608 // 4) Jump to lhs_not_nan. 590 // 4) Jump to lhs_not_nan.
609 // In cases 3 and 4 we have found out we were dealing with a number-number 591 // In cases 3 and 4 we have found out we were dealing with a number-number
610 // comparison. The double values of the numbers have been loaded 592 // comparison. The double values of the numbers have been loaded
611 // into d7 and d6. 593 // into d7 and d6.
612 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); 594 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict());
613 595
614 __ bind(&both_loaded_as_doubles); 596 __ bind(&both_loaded_as_doubles);
615 // The arguments have been converted to doubles and stored in d6 and d7 597 // The arguments have been converted to doubles and stored in d6 and d7
616 __ bind(&lhs_not_nan); 598 __ bind(&lhs_not_nan);
617 Label no_nan; 599 Label no_nan;
618 __ fcmpu(d7, d6); 600 __ cdbr(d7, d6);
619 601
620 Label nan, equal, less_than; 602 Label nan, equal, less_than;
621 __ bunordered(&nan); 603 __ bunordered(&nan);
622 if (CpuFeatures::IsSupported(ISELECT)) { 604 __ beq(&equal, Label::kNear);
623 DCHECK(EQUAL == 0); 605 __ blt(&less_than, Label::kNear);
624 __ li(r4, Operand(GREATER)); 606 __ LoadImmP(r2, Operand(GREATER));
625 __ li(r5, Operand(LESS)); 607 __ Ret();
626 __ isel(eq, r3, r0, r4); 608 __ bind(&equal);
627 __ isel(lt, r3, r5, r3); 609 __ LoadImmP(r2, Operand(EQUAL));
628 __ Ret(); 610 __ Ret();
629 } else { 611 __ bind(&less_than);
630 __ beq(&equal); 612 __ LoadImmP(r2, Operand(LESS));
631 __ blt(&less_than); 613 __ Ret();
632 __ li(r3, Operand(GREATER));
633 __ Ret();
634 __ bind(&equal);
635 __ li(r3, Operand(EQUAL));
636 __ Ret();
637 __ bind(&less_than);
638 __ li(r3, Operand(LESS));
639 __ Ret();
640 }
641 614
642 __ bind(&nan); 615 __ bind(&nan);
643 // If one of the sides was a NaN then the v flag is set. Load r3 with 616 // If one of the sides was a NaN then the v flag is set. Load r2 with
644 // whatever it takes to make the comparison fail, since comparisons with NaN 617 // whatever it takes to make the comparison fail, since comparisons with NaN
645 // always fail. 618 // always fail.
646 if (cc == lt || cc == le) { 619 if (cc == lt || cc == le) {
647 __ li(r3, Operand(GREATER)); 620 __ LoadImmP(r2, Operand(GREATER));
648 } else { 621 } else {
649 __ li(r3, Operand(LESS)); 622 __ LoadImmP(r2, Operand(LESS));
650 } 623 }
651 __ Ret(); 624 __ Ret();
652 625
653 __ bind(&not_smis); 626 __ bind(&not_smis);
654 // At this point we know we are dealing with two different objects, 627 // At this point we know we are dealing with two different objects,
655 // and neither of them is a Smi. The objects are in rhs_ and lhs_. 628 // and neither of them is a Smi. The objects are in rhs_ and lhs_.
656 if (strict()) { 629 if (strict()) {
657 // This returns non-equal for some object types, or falls through if it 630 // This returns non-equal for some object types, or falls through if it
658 // was not lucky. 631 // was not lucky.
659 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); 632 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
660 } 633 }
661 634
662 Label check_for_internalized_strings; 635 Label check_for_internalized_strings;
663 Label flat_string_check; 636 Label flat_string_check;
664 // Check for heap-number-heap-number comparison. Can jump to slow case, 637 // Check for heap-number-heap-number comparison. Can jump to slow case,
665 // or load both doubles into r3, r4, r5, r6 and jump to the code that handles 638 // or load both doubles into r2, r3, r4, r5 and jump to the code that handles
666 // that case. If the inputs are not doubles then jumps to 639 // that case. If the inputs are not doubles then jumps to
667 // check_for_internalized_strings. 640 // check_for_internalized_strings.
668 // In this case r5 will contain the type of rhs_. Never falls through. 641 // In this case r4 will contain the type of rhs_. Never falls through.
669 EmitCheckForTwoHeapNumbers(masm, lhs, rhs, &both_loaded_as_doubles, 642 EmitCheckForTwoHeapNumbers(masm, lhs, rhs, &both_loaded_as_doubles,
670 &check_for_internalized_strings, 643 &check_for_internalized_strings,
671 &flat_string_check); 644 &flat_string_check);
672 645
673 __ bind(&check_for_internalized_strings); 646 __ bind(&check_for_internalized_strings);
674 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of 647 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
675 // internalized strings. 648 // internalized strings.
676 if (cc == eq && !strict()) { 649 if (cc == eq && !strict()) {
677 // Returns an answer for two internalized strings or two detectable objects. 650 // Returns an answer for two internalized strings or two detectable objects.
678 // Otherwise jumps to string case or not both strings case. 651 // Otherwise jumps to string case or not both strings case.
679 // Assumes that r5 is the type of rhs_ on entry. 652 // Assumes that r4 is the type of rhs_ on entry.
680 EmitCheckForInternalizedStringsOrObjects(masm, lhs, rhs, &flat_string_check, 653 EmitCheckForInternalizedStringsOrObjects(masm, lhs, rhs, &flat_string_check,
681 &slow); 654 &slow);
682 } 655 }
683 656
684 // Check for both being sequential one-byte strings, 657 // Check for both being sequential one-byte strings,
685 // and inline if that is the case. 658 // and inline if that is the case.
686 __ bind(&flat_string_check); 659 __ bind(&flat_string_check);
687 660
688 __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, r5, r6, &slow); 661 __ JumpIfNonSmisNotBothSequentialOneByteStrings(lhs, rhs, r4, r5, &slow);
689 662
690 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r5, 663 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r4,
691 r6); 664 r5);
692 if (cc == eq) { 665 if (cc == eq) {
693 StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, r5, r6); 666 StringHelper::GenerateFlatOneByteStringEquals(masm, lhs, rhs, r4, r5);
694 } else { 667 } else {
695 StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r5, r6, r7); 668 StringHelper::GenerateCompareFlatOneByteStrings(masm, lhs, rhs, r4, r5, r6);
696 } 669 }
697 // Never falls through to here. 670 // Never falls through to here.
698 671
699 __ bind(&slow); 672 __ bind(&slow);
700 673
701 __ Push(lhs, rhs); 674 __ Push(lhs, rhs);
702 // Figure out which native to call and setup the arguments. 675 // Figure out which native to call and setup the arguments.
703 if (cc == eq) { 676 if (cc == eq) {
704 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); 677 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
705 } else { 678 } else {
706 int ncr; // NaN compare result 679 int ncr; // NaN compare result
707 if (cc == lt || cc == le) { 680 if (cc == lt || cc == le) {
708 ncr = GREATER; 681 ncr = GREATER;
709 } else { 682 } else {
710 DCHECK(cc == gt || cc == ge); // remaining cases 683 DCHECK(cc == gt || cc == ge); // remaining cases
711 ncr = LESS; 684 ncr = LESS;
712 } 685 }
713 __ LoadSmiLiteral(r3, Smi::FromInt(ncr)); 686 __ LoadSmiLiteral(r2, Smi::FromInt(ncr));
714 __ push(r3); 687 __ push(r2);
715 688
716 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 689 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
717 // tagged as a small integer. 690 // tagged as a small integer.
718 __ TailCallRuntime(Runtime::kCompare); 691 __ TailCallRuntime(Runtime::kCompare);
719 } 692 }
720 693
721 __ bind(&miss); 694 __ bind(&miss);
722 GenerateMiss(masm); 695 GenerateMiss(masm);
723 } 696 }
724 697
725
726 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 698 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
727 // We don't allow a GC during a store buffer overflow so there is no need to 699 // We don't allow a GC during a store buffer overflow so there is no need to
728 // store the registers in any particular way, but we do have to store and 700 // store the registers in any particular way, but we do have to store and
729 // restore them. 701 // restore them.
730 __ mflr(r0); 702 __ MultiPush(kJSCallerSaved | r14.bit());
731 __ MultiPush(kJSCallerSaved | r0.bit());
732 if (save_doubles()) { 703 if (save_doubles()) {
733 __ MultiPushDoubles(kCallerSavedDoubles); 704 __ MultiPushDoubles(kCallerSavedDoubles);
734 } 705 }
735 const int argument_count = 1; 706 const int argument_count = 1;
736 const int fp_argument_count = 0; 707 const int fp_argument_count = 0;
737 const Register scratch = r4; 708 const Register scratch = r3;
738 709
739 AllowExternalCallThatCantCauseGC scope(masm); 710 AllowExternalCallThatCantCauseGC scope(masm);
740 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); 711 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch);
741 __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); 712 __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
742 __ CallCFunction(ExternalReference::store_buffer_overflow_function(isolate()), 713 __ CallCFunction(ExternalReference::store_buffer_overflow_function(isolate()),
743 argument_count); 714 argument_count);
744 if (save_doubles()) { 715 if (save_doubles()) {
745 __ MultiPopDoubles(kCallerSavedDoubles); 716 __ MultiPopDoubles(kCallerSavedDoubles);
746 } 717 }
747 __ MultiPop(kJSCallerSaved | r0.bit()); 718 __ MultiPop(kJSCallerSaved | r14.bit());
748 __ mtlr(r0);
749 __ Ret(); 719 __ Ret();
750 } 720 }
751 721
752
753 void StoreRegistersStateStub::Generate(MacroAssembler* masm) { 722 void StoreRegistersStateStub::Generate(MacroAssembler* masm) {
754 __ PushSafepointRegisters(); 723 __ PushSafepointRegisters();
755 __ blr(); 724 __ b(r14);
756 } 725 }
757 726
758
759 void RestoreRegistersStateStub::Generate(MacroAssembler* masm) { 727 void RestoreRegistersStateStub::Generate(MacroAssembler* masm) {
760 __ PopSafepointRegisters(); 728 __ PopSafepointRegisters();
761 __ blr(); 729 __ b(r14);
762 } 730 }
763 731
764
765 void MathPowStub::Generate(MacroAssembler* masm) { 732 void MathPowStub::Generate(MacroAssembler* masm) {
766 const Register base = r4; 733 const Register base = r3;
767 const Register exponent = MathPowTaggedDescriptor::exponent(); 734 const Register exponent = MathPowTaggedDescriptor::exponent();
768 DCHECK(exponent.is(r5)); 735 DCHECK(exponent.is(r4));
769 const Register heapnumbermap = r8; 736 const Register heapnumbermap = r7;
770 const Register heapnumber = r3; 737 const Register heapnumber = r2;
771 const DoubleRegister double_base = d1; 738 const DoubleRegister double_base = d1;
772 const DoubleRegister double_exponent = d2; 739 const DoubleRegister double_exponent = d2;
773 const DoubleRegister double_result = d3; 740 const DoubleRegister double_result = d3;
774 const DoubleRegister double_scratch = d0; 741 const DoubleRegister double_scratch = d0;
775 const Register scratch = r11; 742 const Register scratch = r1;
776 const Register scratch2 = r10; 743 const Register scratch2 = r9;
777 744
778 Label call_runtime, done, int_exponent; 745 Label call_runtime, done, int_exponent;
779 if (exponent_type() == ON_STACK) { 746 if (exponent_type() == ON_STACK) {
780 Label base_is_smi, unpack_exponent; 747 Label base_is_smi, unpack_exponent;
781 // The exponent and base are supplied as arguments on the stack. 748 // The exponent and base are supplied as arguments on the stack.
782 // This can only happen if the stub is called from non-optimized code. 749 // This can only happen if the stub is called from non-optimized code.
783 // Load input parameters from stack to double registers. 750 // Load input parameters from stack to double registers.
784 __ LoadP(base, MemOperand(sp, 1 * kPointerSize)); 751 __ LoadP(base, MemOperand(sp, 1 * kPointerSize));
785 __ LoadP(exponent, MemOperand(sp, 0 * kPointerSize)); 752 __ LoadP(exponent, MemOperand(sp, 0 * kPointerSize));
786 753
787 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); 754 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
788 755
789 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); 756 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi);
790 __ LoadP(scratch, FieldMemOperand(base, JSObject::kMapOffset)); 757 __ LoadP(scratch, FieldMemOperand(base, JSObject::kMapOffset));
791 __ cmp(scratch, heapnumbermap); 758 __ CmpP(scratch, heapnumbermap);
792 __ bne(&call_runtime); 759 __ bne(&call_runtime);
793 760
794 __ lfd(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); 761 __ LoadDouble(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
795 __ b(&unpack_exponent); 762 __ b(&unpack_exponent, Label::kNear);
796 763
797 __ bind(&base_is_smi); 764 __ bind(&base_is_smi);
798 __ ConvertIntToDouble(scratch, double_base); 765 __ ConvertIntToDouble(scratch, double_base);
799 __ bind(&unpack_exponent); 766 __ bind(&unpack_exponent);
800 767
801 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 768 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
802 __ LoadP(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); 769 __ LoadP(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
803 __ cmp(scratch, heapnumbermap); 770 __ CmpP(scratch, heapnumbermap);
804 __ bne(&call_runtime); 771 __ bne(&call_runtime);
805 772
806 __ lfd(double_exponent, 773 __ LoadDouble(double_exponent,
807 FieldMemOperand(exponent, HeapNumber::kValueOffset)); 774 FieldMemOperand(exponent, HeapNumber::kValueOffset));
808 } else if (exponent_type() == TAGGED) { 775 } else if (exponent_type() == TAGGED) {
809 // Base is already in double_base. 776 // Base is already in double_base.
810 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 777 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
811 778
812 __ lfd(double_exponent, 779 __ LoadDouble(double_exponent,
813 FieldMemOperand(exponent, HeapNumber::kValueOffset)); 780 FieldMemOperand(exponent, HeapNumber::kValueOffset));
814 } 781 }
815 782
816 if (exponent_type() != INTEGER) { 783 if (exponent_type() != INTEGER) {
817 // Detect integer exponents stored as double. 784 // Detect integer exponents stored as double.
818 __ TryDoubleToInt32Exact(scratch, double_exponent, scratch2, 785 __ TryDoubleToInt32Exact(scratch, double_exponent, scratch2,
819 double_scratch); 786 double_scratch);
820 __ beq(&int_exponent); 787 __ beq(&int_exponent, Label::kNear);
821 788
822 if (exponent_type() == ON_STACK) { 789 if (exponent_type() == ON_STACK) {
823 // Detect square root case. Crankshaft detects constant +/-0.5 at 790 // Detect square root case. Crankshaft detects constant +/-0.5 at
824 // compile time and uses DoMathPowHalf instead. We then skip this check 791 // compile time and uses DoMathPowHalf instead. We then skip this check
825 // for non-constant cases of +/-0.5 as these hardly occur. 792 // for non-constant cases of +/-0.5 as these hardly occur.
826 Label not_plus_half, not_minus_inf1, not_minus_inf2; 793 Label not_plus_half, not_minus_inf1, not_minus_inf2;
827 794
828 // Test for 0.5. 795 // Test for 0.5.
829 __ LoadDoubleLiteral(double_scratch, 0.5, scratch); 796 __ LoadDoubleLiteral(double_scratch, 0.5, scratch);
830 __ fcmpu(double_exponent, double_scratch); 797 __ cdbr(double_exponent, double_scratch);
831 __ bne(&not_plus_half); 798 __ bne(&not_plus_half, Label::kNear);
832 799
833 // Calculates square root of base. Check for the special case of 800 // Calculates square root of base. Check for the special case of
834 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). 801 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
835 __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch); 802 __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch);
836 __ fcmpu(double_base, double_scratch); 803 __ cdbr(double_base, double_scratch);
837 __ bne(&not_minus_inf1); 804 __ bne(&not_minus_inf1, Label::kNear);
838 __ fneg(double_result, double_scratch); 805 __ lcdbr(double_result, double_scratch);
839 __ b(&done); 806 __ b(&done);
840 __ bind(&not_minus_inf1); 807 __ bind(&not_minus_inf1);
841 808
842 // Add +0 to convert -0 to +0. 809 // Add +0 to convert -0 to +0.
843 __ fadd(double_scratch, double_base, kDoubleRegZero); 810 __ ldr(double_scratch, double_base);
844 __ fsqrt(double_result, double_scratch); 811 __ lzdr(kDoubleRegZero);
812 __ adbr(double_scratch, kDoubleRegZero);
813 __ sqdbr(double_result, double_scratch);
845 __ b(&done); 814 __ b(&done);
846 815
847 __ bind(&not_plus_half); 816 __ bind(&not_plus_half);
848 __ LoadDoubleLiteral(double_scratch, -0.5, scratch); 817 __ LoadDoubleLiteral(double_scratch, -0.5, scratch);
849 __ fcmpu(double_exponent, double_scratch); 818 __ cdbr(double_exponent, double_scratch);
850 __ bne(&call_runtime); 819 __ bne(&call_runtime);
851 820
852 // Calculates square root of base. Check for the special case of 821 // Calculates square root of base. Check for the special case of
853 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). 822 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
854 __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch); 823 __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch);
855 __ fcmpu(double_base, double_scratch); 824 __ cdbr(double_base, double_scratch);
856 __ bne(&not_minus_inf2); 825 __ bne(&not_minus_inf2, Label::kNear);
857 __ fmr(double_result, kDoubleRegZero); 826 __ ldr(double_result, kDoubleRegZero);
858 __ b(&done); 827 __ b(&done);
859 __ bind(&not_minus_inf2); 828 __ bind(&not_minus_inf2);
860 829
861 // Add +0 to convert -0 to +0. 830 // Add +0 to convert -0 to +0.
862 __ fadd(double_scratch, double_base, kDoubleRegZero); 831 __ ldr(double_scratch, double_base);
832 __ lzdr(kDoubleRegZero);
833 __ adbr(double_scratch, kDoubleRegZero);
863 __ LoadDoubleLiteral(double_result, 1.0, scratch); 834 __ LoadDoubleLiteral(double_result, 1.0, scratch);
864 __ fsqrt(double_scratch, double_scratch); 835 __ sqdbr(double_scratch, double_scratch);
865 __ fdiv(double_result, double_result, double_scratch); 836 __ ddbr(double_result, double_scratch);
866 __ b(&done); 837 __ b(&done);
867 } 838 }
868 839
869 __ mflr(r0); 840 __ push(r14);
870 __ push(r0);
871 { 841 {
872 AllowExternalCallThatCantCauseGC scope(masm); 842 AllowExternalCallThatCantCauseGC scope(masm);
873 __ PrepareCallCFunction(0, 2, scratch); 843 __ PrepareCallCFunction(0, 2, scratch);
874 __ MovToFloatParameters(double_base, double_exponent); 844 __ MovToFloatParameters(double_base, double_exponent);
875 __ CallCFunction( 845 __ CallCFunction(
876 ExternalReference::power_double_double_function(isolate()), 0, 2); 846 ExternalReference::power_double_double_function(isolate()), 0, 2);
877 } 847 }
878 __ pop(r0); 848 __ pop(r14);
879 __ mtlr(r0);
880 __ MovFromFloatResult(double_result); 849 __ MovFromFloatResult(double_result);
881 __ b(&done); 850 __ b(&done);
882 } 851 }
883 852
884 // Calculate power with integer exponent. 853 // Calculate power with integer exponent.
885 __ bind(&int_exponent); 854 __ bind(&int_exponent);
886 855
887 // Get two copies of exponent in the registers scratch and exponent. 856 // Get two copies of exponent in the registers scratch and exponent.
888 if (exponent_type() == INTEGER) { 857 if (exponent_type() == INTEGER) {
889 __ mr(scratch, exponent); 858 __ LoadRR(scratch, exponent);
890 } else { 859 } else {
891 // Exponent has previously been stored into scratch as untagged integer. 860 // Exponent has previously been stored into scratch as untagged integer.
892 __ mr(exponent, scratch); 861 __ LoadRR(exponent, scratch);
893 } 862 }
894 __ fmr(double_scratch, double_base); // Back up base. 863 __ ldr(double_scratch, double_base); // Back up base.
895 __ li(scratch2, Operand(1)); 864 __ LoadImmP(scratch2, Operand(1));
896 __ ConvertIntToDouble(scratch2, double_result); 865 __ ConvertIntToDouble(scratch2, double_result);
897 866
898 // Get absolute value of exponent. 867 // Get absolute value of exponent.
899 __ cmpi(scratch, Operand::Zero()); 868 Label positive_exponent;
900 if (CpuFeatures::IsSupported(ISELECT)) { 869 __ CmpP(scratch, Operand::Zero());
901 __ neg(scratch2, scratch); 870 __ bge(&positive_exponent, Label::kNear);
902 __ isel(lt, scratch, scratch2, scratch); 871 __ LoadComplementRR(scratch, scratch);
903 } else { 872 __ bind(&positive_exponent);
904 Label positive_exponent;
905 __ bge(&positive_exponent);
906 __ neg(scratch, scratch);
907 __ bind(&positive_exponent);
908 }
909 873
910 Label while_true, no_carry, loop_end; 874 Label while_true, no_carry, loop_end;
911 __ bind(&while_true); 875 __ bind(&while_true);
912 __ andi(scratch2, scratch, Operand(1)); 876 __ mov(scratch2, Operand(1));
913 __ beq(&no_carry, cr0); 877 __ AndP(scratch2, scratch);
914 __ fmul(double_result, double_result, double_scratch); 878 __ beq(&no_carry, Label::kNear);
879 __ mdbr(double_result, double_scratch);
915 __ bind(&no_carry); 880 __ bind(&no_carry);
916 __ ShiftRightArithImm(scratch, scratch, 1, SetRC); 881 __ ShiftRightArithP(scratch, scratch, Operand(1));
917 __ beq(&loop_end, cr0); 882 __ beq(&loop_end, Label::kNear);
918 __ fmul(double_scratch, double_scratch, double_scratch); 883 __ mdbr(double_scratch, double_scratch);
919 __ b(&while_true); 884 __ b(&while_true);
920 __ bind(&loop_end); 885 __ bind(&loop_end);
921 886
922 __ cmpi(exponent, Operand::Zero()); 887 __ CmpP(exponent, Operand::Zero());
923 __ bge(&done); 888 __ bge(&done);
924 889
925 __ li(scratch2, Operand(1)); 890 // get 1/double_result:
926 __ ConvertIntToDouble(scratch2, double_scratch); 891 __ ldr(double_scratch, double_result);
927 __ fdiv(double_result, double_scratch, double_result); 892 __ LoadImmP(scratch2, Operand(1));
893 __ ConvertIntToDouble(scratch2, double_result);
894 __ ddbr(double_result, double_scratch);
895
928 // Test whether result is zero. Bail out to check for subnormal result. 896 // Test whether result is zero. Bail out to check for subnormal result.
929 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 897 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
930 __ fcmpu(double_result, kDoubleRegZero); 898 __ lzdr(kDoubleRegZero);
931 __ bne(&done); 899 __ cdbr(double_result, kDoubleRegZero);
900 __ bne(&done, Label::kNear);
932 // double_exponent may not containe the exponent value if the input was a 901 // double_exponent may not containe the exponent value if the input was a
933 // smi. We set it with exponent value before bailing out. 902 // smi. We set it with exponent value before bailing out.
934 __ ConvertIntToDouble(exponent, double_exponent); 903 __ ConvertIntToDouble(exponent, double_exponent);
935 904
936 // Returning or bailing out. 905 // Returning or bailing out.
937 if (exponent_type() == ON_STACK) { 906 if (exponent_type() == ON_STACK) {
938 // The arguments are still on the stack. 907 // The arguments are still on the stack.
939 __ bind(&call_runtime); 908 __ bind(&call_runtime);
940 __ TailCallRuntime(Runtime::kMathPowRT); 909 __ TailCallRuntime(Runtime::kMathPowRT);
941 910
942 // The stub is called from non-optimized code, which expects the result 911 // The stub is called from non-optimized code, which expects the result
943 // as heap number in exponent. 912 // as heap number in exponent.
944 __ bind(&done); 913 __ bind(&done);
945 __ AllocateHeapNumber(heapnumber, scratch, scratch2, heapnumbermap, 914 __ AllocateHeapNumber(heapnumber, scratch, scratch2, heapnumbermap,
946 &call_runtime); 915 &call_runtime);
947 __ stfd(double_result, 916 __ StoreDouble(double_result,
948 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); 917 FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
949 DCHECK(heapnumber.is(r3)); 918 DCHECK(heapnumber.is(r2));
950 __ Ret(2); 919 __ Ret(2);
951 } else { 920 } else {
952 __ mflr(r0); 921 __ push(r14);
953 __ push(r0);
954 { 922 {
955 AllowExternalCallThatCantCauseGC scope(masm); 923 AllowExternalCallThatCantCauseGC scope(masm);
956 __ PrepareCallCFunction(0, 2, scratch); 924 __ PrepareCallCFunction(0, 2, scratch);
957 __ MovToFloatParameters(double_base, double_exponent); 925 __ MovToFloatParameters(double_base, double_exponent);
958 __ CallCFunction( 926 __ CallCFunction(
959 ExternalReference::power_double_double_function(isolate()), 0, 2); 927 ExternalReference::power_double_double_function(isolate()), 0, 2);
960 } 928 }
961 __ pop(r0); 929 __ pop(r14);
962 __ mtlr(r0);
963 __ MovFromFloatResult(double_result); 930 __ MovFromFloatResult(double_result);
964 931
965 __ bind(&done); 932 __ bind(&done);
966 __ Ret(); 933 __ Ret();
967 } 934 }
968 } 935 }
969 936
970
971 bool CEntryStub::NeedsImmovableCode() { return true; } 937 bool CEntryStub::NeedsImmovableCode() { return true; }
972 938
973
974 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 939 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
975 CEntryStub::GenerateAheadOfTime(isolate); 940 CEntryStub::GenerateAheadOfTime(isolate);
976 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 941 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
977 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 942 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
978 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 943 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
979 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 944 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
980 CreateWeakCellStub::GenerateAheadOfTime(isolate); 945 CreateWeakCellStub::GenerateAheadOfTime(isolate);
981 BinaryOpICStub::GenerateAheadOfTime(isolate); 946 BinaryOpICStub::GenerateAheadOfTime(isolate);
982 StoreRegistersStateStub::GenerateAheadOfTime(isolate); 947 StoreRegistersStateStub::GenerateAheadOfTime(isolate);
983 RestoreRegistersStateStub::GenerateAheadOfTime(isolate); 948 RestoreRegistersStateStub::GenerateAheadOfTime(isolate);
984 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 949 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
985 StoreFastElementStub::GenerateAheadOfTime(isolate); 950 StoreFastElementStub::GenerateAheadOfTime(isolate);
986 TypeofStub::GenerateAheadOfTime(isolate); 951 TypeofStub::GenerateAheadOfTime(isolate);
987 } 952 }
988 953
989
990 void StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 954 void StoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) {
991 StoreRegistersStateStub stub(isolate); 955 StoreRegistersStateStub stub(isolate);
992 stub.GetCode(); 956 stub.GetCode();
993 } 957 }
994 958
995
996 void RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) { 959 void RestoreRegistersStateStub::GenerateAheadOfTime(Isolate* isolate) {
997 RestoreRegistersStateStub stub(isolate); 960 RestoreRegistersStateStub stub(isolate);
998 stub.GetCode(); 961 stub.GetCode();
999 } 962 }
1000 963
1001
1002 void CodeStub::GenerateFPStubs(Isolate* isolate) { 964 void CodeStub::GenerateFPStubs(Isolate* isolate) {
1003 // Generate if not already in cache.
1004 SaveFPRegsMode mode = kSaveFPRegs; 965 SaveFPRegsMode mode = kSaveFPRegs;
1005 CEntryStub(isolate, 1, mode).GetCode(); 966 CEntryStub(isolate, 1, mode).GetCode();
1006 StoreBufferOverflowStub(isolate, mode).GetCode(); 967 StoreBufferOverflowStub(isolate, mode).GetCode();
1007 isolate->set_fp_stubs_generated(true); 968 isolate->set_fp_stubs_generated(true);
1008 } 969 }
1009 970
1010
1011 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 971 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
1012 CEntryStub stub(isolate, 1, kDontSaveFPRegs); 972 CEntryStub stub(isolate, 1, kDontSaveFPRegs);
1013 stub.GetCode(); 973 stub.GetCode();
1014 } 974 }
1015 975
1016
1017 void CEntryStub::Generate(MacroAssembler* masm) { 976 void CEntryStub::Generate(MacroAssembler* masm) {
1018 // Called from JavaScript; parameters are on stack as if calling JS function. 977 // Called from JavaScript; parameters are on stack as if calling JS function.
1019 // r3: number of arguments including receiver 978 // r2: number of arguments including receiver
1020 // r4: pointer to builtin function 979 // r3: pointer to builtin function
1021 // fp: frame pointer (restored after C call) 980 // fp: frame pointer (restored after C call)
1022 // sp: stack pointer (restored as callee's sp after C call) 981 // sp: stack pointer (restored as callee's sp after C call)
1023 // cp: current context (C callee-saved) 982 // cp: current context (C callee-saved)
1024 // 983 //
1025 // If argv_in_register(): 984 // If argv_in_register():
1026 // r5: pointer to the first argument 985 // r4: pointer to the first argument
1027 ProfileEntryHookStub::MaybeCallEntryHook(masm); 986 ProfileEntryHookStub::MaybeCallEntryHook(masm);
1028 987
1029 __ mr(r15, r4); 988 __ LoadRR(r7, r3);
1030 989
1031 if (argv_in_register()) { 990 if (argv_in_register()) {
1032 // Move argv into the correct register. 991 // Move argv into the correct register.
1033 __ mr(r4, r5); 992 __ LoadRR(r3, r4);
1034 } else { 993 } else {
1035 // Compute the argv pointer. 994 // Compute the argv pointer.
1036 __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2)); 995 __ ShiftLeftP(r3, r2, Operand(kPointerSizeLog2));
1037 __ add(r4, r4, sp); 996 __ lay(r3, MemOperand(r3, sp, -kPointerSize));
1038 __ subi(r4, r4, Operand(kPointerSize));
1039 } 997 }
1040 998
1041 // Enter the exit frame that transitions from JavaScript to C++. 999 // Enter the exit frame that transitions from JavaScript to C++.
1042 FrameScope scope(masm, StackFrame::MANUAL); 1000 FrameScope scope(masm, StackFrame::MANUAL);
1043 1001
1044 // Need at least one extra slot for return address location. 1002 // Need at least one extra slot for return address location.
1045 int arg_stack_space = 1; 1003 int arg_stack_space = 1;
1046 1004
1047 // Pass buffer for return value on stack if necessary 1005 // Pass buffer for return value on stack if necessary
1048 bool needs_return_buffer = 1006 bool needs_return_buffer =
1049 result_size() > 2 || 1007 result_size() > 2 ||
1050 (result_size() == 2 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS); 1008 (result_size() == 2 && !ABI_RETURNS_OBJECTPAIR_IN_REGS);
1051 if (needs_return_buffer) { 1009 if (needs_return_buffer) {
1052 arg_stack_space += result_size(); 1010 arg_stack_space += result_size();
1053 } 1011 }
1054 1012
1013 #if V8_TARGET_ARCH_S390X
1014 // 64-bit linux pass Argument object by reference not value
1015 arg_stack_space += 2;
1016 #endif
1017
1055 __ EnterExitFrame(save_doubles(), arg_stack_space); 1018 __ EnterExitFrame(save_doubles(), arg_stack_space);
1056 1019
1057 // Store a copy of argc in callee-saved registers for later. 1020 // Store a copy of argc, argv in callee-saved registers for later.
1058 __ mr(r14, r3); 1021 __ LoadRR(r6, r2);
1059 1022 __ LoadRR(r8, r3);
1060 // r3, r14: number of arguments including receiver (C callee-saved) 1023 // r2, r6: number of arguments including receiver (C callee-saved)
1061 // r4: pointer to the first argument 1024 // r3, r8: pointer to the first argument
1062 // r15: pointer to builtin function (C callee-saved) 1025 // r7: pointer to builtin function (C callee-saved)
1063 1026
1064 // Result returned in registers or stack, depending on result size and ABI. 1027 // Result returned in registers or stack, depending on result size and ABI.
1065 1028
1066 Register isolate_reg = r5; 1029 Register isolate_reg = r4;
1067 if (needs_return_buffer) { 1030 if (needs_return_buffer) {
1068 // The return value is a non-scalar value. 1031 // The return value is 16-byte non-scalar value.
1069 // Use frame storage reserved by calling function to pass return 1032 // Use frame storage reserved by calling function to pass return
1070 // buffer as implicit first argument. 1033 // buffer as implicit first argument in R2. Shfit original parameters
1071 __ mr(r5, r4); 1034 // by one register each.
1072 __ mr(r4, r3); 1035 __ LoadRR(r4, r3);
1073 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize)); 1036 __ LoadRR(r3, r2);
1074 isolate_reg = r6; 1037 __ la(r2, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize));
1038 isolate_reg = r5;
1075 } 1039 }
1076
1077 // Call C built-in. 1040 // Call C built-in.
1078 __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate()))); 1041 __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate())));
1079 1042
1080 Register target = r15; 1043 Register target = r7;
1081 if (ABI_USES_FUNCTION_DESCRIPTORS) {
1082 // AIX/PPC64BE Linux use a function descriptor.
1083 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
1084 __ LoadP(ip, MemOperand(r15, 0)); // Instruction address
1085 target = ip;
1086 } else if (ABI_CALL_VIA_IP) {
1087 __ Move(ip, r15);
1088 target = ip;
1089 }
1090 1044
1091 // To let the GC traverse the return address of the exit frames, we need to 1045 // To let the GC traverse the return address of the exit frames, we need to
1092 // know where the return address is. The CEntryStub is unmovable, so 1046 // know where the return address is. The CEntryStub is unmovable, so
1093 // we can store the address on the stack to be able to find it again and 1047 // we can store the address on the stack to be able to find it again and
1094 // we never have to restore it, because it will not change. 1048 // we never have to restore it, because it will not change.
1095 Label after_call; 1049 {
1096 __ mov_label_addr(r0, &after_call); 1050 Label return_label;
1097 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 1051 __ larl(r14, &return_label); // Generate the return addr of call later.
1098 __ Call(target); 1052 __ StoreP(r14, MemOperand(sp, kStackFrameRASlot * kPointerSize));
1099 __ bind(&after_call); 1053
1054 // zLinux ABI requires caller's frame to have sufficient space for callee
1055 // preserved regsiter save area.
1056 // __ lay(sp, MemOperand(sp, -kCalleeRegisterSaveAreaSize));
1057 __ positions_recorder()->WriteRecordedPositions();
1058 __ b(target);
1059 __ bind(&return_label);
1060 // __ la(sp, MemOperand(sp, +kCalleeRegisterSaveAreaSize));
1061 }
1100 1062
1101 // If return value is on the stack, pop it to registers. 1063 // If return value is on the stack, pop it to registers.
1102 if (needs_return_buffer) { 1064 if (needs_return_buffer) {
1103 if (result_size() > 2) __ LoadP(r5, MemOperand(r3, 2 * kPointerSize)); 1065 if (result_size() > 2) __ LoadP(r4, MemOperand(r2, 2 * kPointerSize));
1104 __ LoadP(r4, MemOperand(r3, kPointerSize)); 1066 __ LoadP(r3, MemOperand(r2, kPointerSize));
1105 __ LoadP(r3, MemOperand(r3)); 1067 __ LoadP(r2, MemOperand(r2));
1106 } 1068 }
1107 1069
1108 // Check result for exception sentinel. 1070 // Check result for exception sentinel.
1109 Label exception_returned; 1071 Label exception_returned;
1110 __ CompareRoot(r3, Heap::kExceptionRootIndex); 1072 __ CompareRoot(r2, Heap::kExceptionRootIndex);
1111 __ beq(&exception_returned); 1073 __ beq(&exception_returned, Label::kNear);
1112 1074
1113 // Check that there is no pending exception, otherwise we 1075 // Check that there is no pending exception, otherwise we
1114 // should have returned the exception sentinel. 1076 // should have returned the exception sentinel.
1115 if (FLAG_debug_code) { 1077 if (FLAG_debug_code) {
1116 Label okay; 1078 Label okay;
1117 ExternalReference pending_exception_address( 1079 ExternalReference pending_exception_address(
1118 Isolate::kPendingExceptionAddress, isolate()); 1080 Isolate::kPendingExceptionAddress, isolate());
1119 1081 __ mov(r4, Operand(pending_exception_address));
1120 __ mov(r6, Operand(pending_exception_address)); 1082 __ LoadP(r4, MemOperand(r4));
1121 __ LoadP(r6, MemOperand(r6)); 1083 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
1122 __ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
1123 // Cannot use check here as it attempts to generate call into runtime. 1084 // Cannot use check here as it attempts to generate call into runtime.
1124 __ beq(&okay); 1085 __ beq(&okay, Label::kNear);
1125 __ stop("Unexpected pending exception"); 1086 __ stop("Unexpected pending exception");
1126 __ bind(&okay); 1087 __ bind(&okay);
1127 } 1088 }
1128 1089
1129 // Exit C frame and return. 1090 // Exit C frame and return.
1130 // r3:r4: result 1091 // r2:r3: result
1131 // sp: stack pointer 1092 // sp: stack pointer
1132 // fp: frame pointer 1093 // fp: frame pointer
1133 Register argc; 1094 Register argc;
1134 if (argv_in_register()) { 1095 if (argv_in_register()) {
1135 // We don't want to pop arguments so set argc to no_reg. 1096 // We don't want to pop arguments so set argc to no_reg.
1136 argc = no_reg; 1097 argc = no_reg;
1137 } else { 1098 } else {
1138 // r14: still holds argc (callee-saved). 1099 // r6: still holds argc (callee-saved).
1139 argc = r14; 1100 argc = r6;
1140 } 1101 }
1141 __ LeaveExitFrame(save_doubles(), argc, true); 1102 __ LeaveExitFrame(save_doubles(), argc, true);
1142 __ blr(); 1103 __ b(r14);
1143 1104
1144 // Handling of exception. 1105 // Handling of exception.
1145 __ bind(&exception_returned); 1106 __ bind(&exception_returned);
1146 1107
1147 ExternalReference pending_handler_context_address( 1108 ExternalReference pending_handler_context_address(
1148 Isolate::kPendingHandlerContextAddress, isolate()); 1109 Isolate::kPendingHandlerContextAddress, isolate());
1149 ExternalReference pending_handler_code_address( 1110 ExternalReference pending_handler_code_address(
1150 Isolate::kPendingHandlerCodeAddress, isolate()); 1111 Isolate::kPendingHandlerCodeAddress, isolate());
1151 ExternalReference pending_handler_offset_address( 1112 ExternalReference pending_handler_offset_address(
1152 Isolate::kPendingHandlerOffsetAddress, isolate()); 1113 Isolate::kPendingHandlerOffsetAddress, isolate());
1153 ExternalReference pending_handler_fp_address( 1114 ExternalReference pending_handler_fp_address(
1154 Isolate::kPendingHandlerFPAddress, isolate()); 1115 Isolate::kPendingHandlerFPAddress, isolate());
1155 ExternalReference pending_handler_sp_address( 1116 ExternalReference pending_handler_sp_address(
1156 Isolate::kPendingHandlerSPAddress, isolate()); 1117 Isolate::kPendingHandlerSPAddress, isolate());
1157 1118
1158 // Ask the runtime for help to determine the handler. This will set r3 to 1119 // Ask the runtime for help to determine the handler. This will set r3 to
1159 // contain the current pending exception, don't clobber it. 1120 // contain the current pending exception, don't clobber it.
1160 ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler, 1121 ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
1161 isolate()); 1122 isolate());
1162 { 1123 {
1163 FrameScope scope(masm, StackFrame::MANUAL); 1124 FrameScope scope(masm, StackFrame::MANUAL);
1164 __ PrepareCallCFunction(3, 0, r3); 1125 __ PrepareCallCFunction(3, 0, r2);
1165 __ li(r3, Operand::Zero()); 1126 __ LoadImmP(r2, Operand::Zero());
1166 __ li(r4, Operand::Zero()); 1127 __ LoadImmP(r3, Operand::Zero());
1167 __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 1128 __ mov(r4, Operand(ExternalReference::isolate_address(isolate())));
1168 __ CallCFunction(find_handler, 3); 1129 __ CallCFunction(find_handler, 3);
1169 } 1130 }
1170 1131
1171 // Retrieve the handler context, SP and FP. 1132 // Retrieve the handler context, SP and FP.
1172 __ mov(cp, Operand(pending_handler_context_address)); 1133 __ mov(cp, Operand(pending_handler_context_address));
1173 __ LoadP(cp, MemOperand(cp)); 1134 __ LoadP(cp, MemOperand(cp));
1174 __ mov(sp, Operand(pending_handler_sp_address)); 1135 __ mov(sp, Operand(pending_handler_sp_address));
1175 __ LoadP(sp, MemOperand(sp)); 1136 __ LoadP(sp, MemOperand(sp));
1176 __ mov(fp, Operand(pending_handler_fp_address)); 1137 __ mov(fp, Operand(pending_handler_fp_address));
1177 __ LoadP(fp, MemOperand(fp)); 1138 __ LoadP(fp, MemOperand(fp));
1178 1139
1179 // If the handler is a JS frame, restore the context to the frame. Note that 1140 // If the handler is a JS frame, restore the context to the frame. Note that
1180 // the context will be set to (cp == 0) for non-JS frames. 1141 // the context will be set to (cp == 0) for non-JS frames.
1181 Label skip; 1142 Label skip;
1182 __ cmpi(cp, Operand::Zero()); 1143 __ CmpP(cp, Operand::Zero());
1183 __ beq(&skip); 1144 __ beq(&skip, Label::kNear);
1184 __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1145 __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1185 __ bind(&skip); 1146 __ bind(&skip);
1186 1147
1187 // Compute the handler entry address and jump to it. 1148 // Compute the handler entry address and jump to it.
1188 ConstantPoolUnavailableScope constant_pool_unavailable(masm); 1149 __ mov(r3, Operand(pending_handler_code_address));
1189 __ mov(r4, Operand(pending_handler_code_address)); 1150 __ LoadP(r3, MemOperand(r3));
1151 __ mov(r4, Operand(pending_handler_offset_address));
1190 __ LoadP(r4, MemOperand(r4)); 1152 __ LoadP(r4, MemOperand(r4));
1191 __ mov(r5, Operand(pending_handler_offset_address)); 1153 __ AddP(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start
1192 __ LoadP(r5, MemOperand(r5)); 1154 __ AddP(ip, r3, r4);
1193 __ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start
1194 if (FLAG_enable_embedded_constant_pool) {
1195 __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r4);
1196 }
1197 __ add(ip, r4, r5);
1198 __ Jump(ip); 1155 __ Jump(ip);
1199 } 1156 }
1200 1157
1201
1202 void JSEntryStub::Generate(MacroAssembler* masm) { 1158 void JSEntryStub::Generate(MacroAssembler* masm) {
1203 // r3: code entry 1159 // r2: code entry
1204 // r4: function 1160 // r3: function
1205 // r5: receiver 1161 // r4: receiver
1206 // r6: argc 1162 // r5: argc
1207 // [sp+0]: argv 1163 // r6: argv
1208 1164
1209 Label invoke, handler_entry, exit; 1165 Label invoke, handler_entry, exit;
1210 1166
1211 // Called from C
1212 __ function_descriptor();
1213
1214 ProfileEntryHookStub::MaybeCallEntryHook(masm); 1167 ProfileEntryHookStub::MaybeCallEntryHook(masm);
1215 1168
1216 // PPC LINUX ABI: 1169 // saving floating point registers
1217 // preserve LR in pre-reserved slot in caller's frame 1170 #if V8_HOST_ARCH_S390X
1218 __ mflr(r0); 1171 // 64bit ABI requires f8 to f15 be saved
1219 __ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize)); 1172 __ lay(sp, MemOperand(sp, -8 * kDoubleSize));
1173 __ std(d8, MemOperand(sp));
1174 __ std(d9, MemOperand(sp, 1 * kDoubleSize));
1175 __ std(d10, MemOperand(sp, 2 * kDoubleSize));
1176 __ std(d11, MemOperand(sp, 3 * kDoubleSize));
1177 __ std(d12, MemOperand(sp, 4 * kDoubleSize));
1178 __ std(d13, MemOperand(sp, 5 * kDoubleSize));
1179 __ std(d14, MemOperand(sp, 6 * kDoubleSize));
1180 __ std(d15, MemOperand(sp, 7 * kDoubleSize));
1181 #else
1182 // 31bit ABI requires you to store f4 and f6:
1183 // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN417
1184 __ lay(sp, MemOperand(sp, -2 * kDoubleSize));
1185 __ std(d4, MemOperand(sp));
1186 __ std(d6, MemOperand(sp, kDoubleSize));
1187 #endif
1220 1188
1221 // Save callee saved registers on the stack. 1189 // zLinux ABI
1222 __ MultiPush(kCalleeSaved); 1190 // Incoming parameters:
1191 // r2: code entry
1192 // r3: function
1193 // r4: receiver
1194 // r5: argc
1195 // r6: argv
1196 // Requires us to save the callee-preserved registers r6-r13
1197 // General convention is to also save r14 (return addr) and
1198 // sp/r15 as well in a single STM/STMG
1199 __ lay(sp, MemOperand(sp, -10 * kPointerSize));
1200 __ StoreMultipleP(r6, sp, MemOperand(sp, 0));
1223 1201
1224 // Save callee-saved double registers.
1225 __ MultiPushDoubles(kCalleeSavedDoubles);
1226 // Set up the reserved register for 0.0. 1202 // Set up the reserved register for 0.0.
1227 __ LoadDoubleLiteral(kDoubleRegZero, 0.0, r0); 1203 // __ LoadDoubleLiteral(kDoubleRegZero, 0.0, r0);
1228 1204
1229 // Push a frame with special values setup to mark it as an entry frame. 1205 // Push a frame with special values setup to mark it as an entry frame.
1230 // r3: code entry 1206 // Bad FP (-1)
1231 // r4: function 1207 // SMI Marker
1232 // r5: receiver 1208 // SMI Marker
1233 // r6: argc 1209 // kCEntryFPAddress
1234 // r7: argv 1210 // Frame type
1235 __ li(r0, Operand(-1)); // Push a bad frame pointer to fail if it is used. 1211 __ lay(sp, MemOperand(sp, -5 * kPointerSize));
1236 __ push(r0); 1212 // Push a bad frame pointer to fail if it is used.
1237 if (FLAG_enable_embedded_constant_pool) { 1213 __ LoadImmP(r10, Operand(-1));
1238 __ li(kConstantPoolRegister, Operand::Zero()); 1214
1239 __ push(kConstantPoolRegister);
1240 }
1241 int marker = type(); 1215 int marker = type();
1242 __ LoadSmiLiteral(r0, Smi::FromInt(marker)); 1216 __ LoadSmiLiteral(r9, Smi::FromInt(marker));
1243 __ push(r0); 1217 __ LoadSmiLiteral(r8, Smi::FromInt(marker));
1244 __ push(r0);
1245 // Save copies of the top frame descriptor on the stack. 1218 // Save copies of the top frame descriptor on the stack.
1246 __ mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1219 __ mov(r7, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1247 __ LoadP(r0, MemOperand(r8)); 1220 __ LoadP(r7, MemOperand(r7));
1248 __ push(r0); 1221 __ StoreMultipleP(r7, r10, MemOperand(sp, kPointerSize));
1249
1250 // Set up frame pointer for the frame to be pushed. 1222 // Set up frame pointer for the frame to be pushed.
1251 __ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1223 // Need to add kPointerSize, because sp has one extra
1224 // frame already for the frame type being pushed later.
1225 __ lay(fp,
1226 MemOperand(sp, -EntryFrameConstants::kCallerFPOffset + kPointerSize));
1252 1227
1253 // If this is the outermost JS call, set js_entry_sp value. 1228 // If this is the outermost JS call, set js_entry_sp value.
1254 Label non_outermost_js; 1229 Label non_outermost_js;
1255 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate()); 1230 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate());
1256 __ mov(r8, Operand(ExternalReference(js_entry_sp))); 1231 __ mov(r7, Operand(ExternalReference(js_entry_sp)));
1257 __ LoadP(r9, MemOperand(r8)); 1232 __ LoadAndTestP(r8, MemOperand(r7));
1258 __ cmpi(r9, Operand::Zero()); 1233 __ bne(&non_outermost_js, Label::kNear);
1259 __ bne(&non_outermost_js); 1234 __ StoreP(fp, MemOperand(r7));
1260 __ StoreP(fp, MemOperand(r8));
1261 __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 1235 __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
1262 Label cont; 1236 Label cont;
1263 __ b(&cont); 1237 __ b(&cont, Label::kNear);
1264 __ bind(&non_outermost_js); 1238 __ bind(&non_outermost_js);
1265 __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)); 1239 __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
1240
1266 __ bind(&cont); 1241 __ bind(&cont);
1267 __ push(ip); // frame-type 1242 __ StoreP(ip, MemOperand(sp)); // frame-type
1268 1243
1269 // Jump to a faked try block that does the invoke, with a faked catch 1244 // Jump to a faked try block that does the invoke, with a faked catch
1270 // block that sets the pending exception. 1245 // block that sets the pending exception.
1271 __ b(&invoke); 1246 __ b(&invoke, Label::kNear);
1272 1247
1273 __ bind(&handler_entry); 1248 __ bind(&handler_entry);
1274 handler_offset_ = handler_entry.pos(); 1249 handler_offset_ = handler_entry.pos();
1275 // Caught exception: Store result (exception) in the pending exception 1250 // Caught exception: Store result (exception) in the pending exception
1276 // field in the JSEnv and return a failure sentinel. Coming in here the 1251 // field in the JSEnv and return a failure sentinel. Coming in here the
1277 // fp will be invalid because the PushStackHandler below sets it to 0 to 1252 // fp will be invalid because the PushStackHandler below sets it to 0 to
1278 // signal the existence of the JSEntry frame. 1253 // signal the existence of the JSEntry frame.
1279 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1254 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1280 isolate()))); 1255 isolate())));
1281 1256
1282 __ StoreP(r3, MemOperand(ip)); 1257 __ StoreP(r2, MemOperand(ip));
1283 __ LoadRoot(r3, Heap::kExceptionRootIndex); 1258 __ LoadRoot(r2, Heap::kExceptionRootIndex);
1284 __ b(&exit); 1259 __ b(&exit, Label::kNear);
1285 1260
1286 // Invoke: Link this frame into the handler chain. 1261 // Invoke: Link this frame into the handler chain.
1287 __ bind(&invoke); 1262 __ bind(&invoke);
1288 // Must preserve r3-r7. 1263 // Must preserve r2-r6.
1289 __ PushStackHandler(); 1264 __ PushStackHandler();
1290 // If an exception not caught by another handler occurs, this handler 1265 // If an exception not caught by another handler occurs, this handler
1291 // returns control to the code after the b(&invoke) above, which 1266 // returns control to the code after the b(&invoke) above, which
1292 // restores all kCalleeSaved registers (including cp and fp) to their 1267 // restores all kCalleeSaved registers (including cp and fp) to their
1293 // saved values before returning a failure to C. 1268 // saved values before returning a failure to C.
1294 1269
1295 // Clear any pending exceptions. 1270 // Clear any pending exceptions.
1296 __ mov(r8, Operand(isolate()->factory()->the_hole_value()));
1297 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1271 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1298 isolate()))); 1272 isolate())));
1299 __ StoreP(r8, MemOperand(ip)); 1273 __ mov(r7, Operand(isolate()->factory()->the_hole_value()));
1274 __ StoreP(r7, MemOperand(ip));
1300 1275
1301 // Invoke the function by calling through JS entry trampoline builtin. 1276 // Invoke the function by calling through JS entry trampoline builtin.
1302 // Notice that we cannot store a reference to the trampoline code directly in 1277 // Notice that we cannot store a reference to the trampoline code directly in
1303 // this stub, because runtime stubs are not traversed when doing GC. 1278 // this stub, because runtime stubs are not traversed when doing GC.
1304 1279
1305 // Expected registers by Builtins::JSEntryTrampoline 1280 // Expected registers by Builtins::JSEntryTrampoline
1306 // r3: code entry 1281 // r2: code entry
1307 // r4: function 1282 // r3: function
1308 // r5: receiver 1283 // r4: receiver
1309 // r6: argc 1284 // r5: argc
1310 // r7: argv 1285 // r6: argv
1311 if (type() == StackFrame::ENTRY_CONSTRUCT) { 1286 if (type() == StackFrame::ENTRY_CONSTRUCT) {
1312 ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 1287 ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
1313 isolate()); 1288 isolate());
1314 __ mov(ip, Operand(construct_entry)); 1289 __ mov(ip, Operand(construct_entry));
1315 } else { 1290 } else {
1316 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate()); 1291 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate());
1317 __ mov(ip, Operand(entry)); 1292 __ mov(ip, Operand(entry));
1318 } 1293 }
1319 __ LoadP(ip, MemOperand(ip)); // deref address 1294 __ LoadP(ip, MemOperand(ip)); // deref address
1320 1295
1321 // Branch and link to JSEntryTrampoline. 1296 // Branch and link to JSEntryTrampoline.
1322 // the address points to the start of the code object, skip the header 1297 // the address points to the start of the code object, skip the header
1323 __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); 1298 __ AddP(ip, Operand(Code::kHeaderSize - kHeapObjectTag));
1324 __ mtctr(ip); 1299 Label return_addr;
1325 __ bctrl(); // make the call 1300 // __ basr(r14, ip);
1301 __ larl(r14, &return_addr);
1302 __ b(ip);
1303 __ bind(&return_addr);
1326 1304
1327 // Unlink this frame from the handler chain. 1305 // Unlink this frame from the handler chain.
1328 __ PopStackHandler(); 1306 __ PopStackHandler();
1329 1307
1330 __ bind(&exit); // r3 holds result 1308 __ bind(&exit); // r2 holds result
1331 // Check if the current stack frame is marked as the outermost JS frame. 1309 // Check if the current stack frame is marked as the outermost JS frame.
1332 Label non_outermost_js_2; 1310 Label non_outermost_js_2;
1333 __ pop(r8); 1311 __ pop(r7);
1334 __ CmpSmiLiteral(r8, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME), r0); 1312 __ CmpSmiLiteral(r7, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME), r0);
1335 __ bne(&non_outermost_js_2); 1313 __ bne(&non_outermost_js_2, Label::kNear);
1336 __ mov(r9, Operand::Zero()); 1314 __ mov(r8, Operand::Zero());
1337 __ mov(r8, Operand(ExternalReference(js_entry_sp))); 1315 __ mov(r7, Operand(ExternalReference(js_entry_sp)));
1338 __ StoreP(r9, MemOperand(r8)); 1316 __ StoreP(r8, MemOperand(r7));
1339 __ bind(&non_outermost_js_2); 1317 __ bind(&non_outermost_js_2);
1340 1318
1341 // Restore the top frame descriptors from the stack. 1319 // Restore the top frame descriptors from the stack.
1342 __ pop(r6); 1320 __ pop(r5);
1343 __ mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1321 __ mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1344 __ StoreP(r6, MemOperand(ip)); 1322 __ StoreP(r5, MemOperand(ip));
1345 1323
1346 // Reset the stack to the callee saved registers. 1324 // Reset the stack to the callee saved registers.
1347 __ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1325 __ lay(sp, MemOperand(sp, -EntryFrameConstants::kCallerFPOffset));
1348 1326
1349 // Restore callee-saved double registers. 1327 // Reload callee-saved preserved regs, return address reg (r14) and sp
1350 __ MultiPopDoubles(kCalleeSavedDoubles); 1328 __ LoadMultipleP(r6, sp, MemOperand(sp, 0));
1329 __ la(sp, MemOperand(sp, 10 * kPointerSize));
1351 1330
1352 // Restore callee-saved registers. 1331 // saving floating point registers
1353 __ MultiPop(kCalleeSaved); 1332 #if V8_HOST_ARCH_S390X
1333 // 64bit ABI requires f8 to f15 be saved
1334 __ ld(d8, MemOperand(sp));
1335 __ ld(d9, MemOperand(sp, 1 * kDoubleSize));
1336 __ ld(d10, MemOperand(sp, 2 * kDoubleSize));
1337 __ ld(d11, MemOperand(sp, 3 * kDoubleSize));
1338 __ ld(d12, MemOperand(sp, 4 * kDoubleSize));
1339 __ ld(d13, MemOperand(sp, 5 * kDoubleSize));
1340 __ ld(d14, MemOperand(sp, 6 * kDoubleSize));
1341 __ ld(d15, MemOperand(sp, 7 * kDoubleSize));
1342 __ la(sp, MemOperand(sp, 8 * kDoubleSize));
1343 #else
1344 // 31bit ABI requires you to store f4 and f6:
1345 // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN417
1346 __ ld(d4, MemOperand(sp));
1347 __ ld(d6, MemOperand(sp, kDoubleSize));
1348 __ la(sp, MemOperand(sp, 2 * kDoubleSize));
1349 #endif
1354 1350
1355 // Return 1351 __ b(r14);
1356 __ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
1357 __ mtlr(r0);
1358 __ blr();
1359 } 1352 }
1360 1353
1361
1362 void InstanceOfStub::Generate(MacroAssembler* masm) { 1354 void InstanceOfStub::Generate(MacroAssembler* masm) {
1363 Register const object = r4; // Object (lhs). 1355 Register const object = r3; // Object (lhs).
1364 Register const function = r3; // Function (rhs). 1356 Register const function = r2; // Function (rhs).
1365 Register const object_map = r5; // Map of {object}. 1357 Register const object_map = r4; // Map of {object}.
1366 Register const function_map = r6; // Map of {function}. 1358 Register const function_map = r5; // Map of {function}.
1367 Register const function_prototype = r7; // Prototype of {function}. 1359 Register const function_prototype = r6; // Prototype of {function}.
1368 Register const scratch = r8; 1360 Register const scratch = r7;
1369 1361
1370 DCHECK(object.is(InstanceOfDescriptor::LeftRegister())); 1362 DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
1371 DCHECK(function.is(InstanceOfDescriptor::RightRegister())); 1363 DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
1372 1364
1373 // Check if {object} is a smi. 1365 // Check if {object} is a smi.
1374 Label object_is_smi; 1366 Label object_is_smi;
1375 __ JumpIfSmi(object, &object_is_smi); 1367 __ JumpIfSmi(object, &object_is_smi);
1376 1368
1377 // Lookup the {function} and the {object} map in the global instanceof cache. 1369 // Lookup the {function} and the {object} map in the global instanceof cache.
1378 // Note: This is safe because we clear the global instanceof cache whenever 1370 // Note: This is safe because we clear the global instanceof cache whenever
1379 // we change the prototype of any object. 1371 // we change the prototype of any object.
1380 Label fast_case, slow_case; 1372 Label fast_case, slow_case;
1381 __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); 1373 __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
1382 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 1374 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
1383 __ bne(&fast_case); 1375 __ bne(&fast_case);
1384 __ CompareRoot(object_map, Heap::kInstanceofCacheMapRootIndex); 1376 __ CompareRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
1385 __ bne(&fast_case); 1377 __ bne(&fast_case);
1386 __ LoadRoot(r3, Heap::kInstanceofCacheAnswerRootIndex); 1378 __ LoadRoot(r2, Heap::kInstanceofCacheAnswerRootIndex);
1387 __ Ret(); 1379 __ Ret();
1388 1380
1389 // If {object} is a smi we can safely return false if {function} is a JS 1381 // If {object} is a smi we can safely return false if {function} is a JS
1390 // function, otherwise we have to miss to the runtime and throw an exception. 1382 // function, otherwise we have to miss to the runtime and throw an exception.
1391 __ bind(&object_is_smi); 1383 __ bind(&object_is_smi);
1392 __ JumpIfSmi(function, &slow_case); 1384 __ JumpIfSmi(function, &slow_case);
1393 __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE); 1385 __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
1394 __ bne(&slow_case); 1386 __ bne(&slow_case);
1395 __ LoadRoot(r3, Heap::kFalseValueRootIndex); 1387 __ LoadRoot(r2, Heap::kFalseValueRootIndex);
1396 __ Ret(); 1388 __ Ret();
1397 1389
1398 // Fast-case: The {function} must be a valid JSFunction. 1390 // Fast-case: The {function} must be a valid JSFunction.
1399 __ bind(&fast_case); 1391 __ bind(&fast_case);
1400 __ JumpIfSmi(function, &slow_case); 1392 __ JumpIfSmi(function, &slow_case);
1401 __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE); 1393 __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
1402 __ bne(&slow_case); 1394 __ bne(&slow_case);
1403 1395
1404 // Ensure that {function} has an instance prototype. 1396 // Ensure that {function} has an instance prototype.
1405 __ lbz(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset)); 1397 __ LoadlB(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
1406 __ TestBit(scratch, Map::kHasNonInstancePrototype, r0); 1398 __ TestBit(scratch, Map::kHasNonInstancePrototype, r0);
1407 __ bne(&slow_case, cr0); 1399 __ bne(&slow_case);
1408 1400
1409 // Get the "prototype" (or initial map) of the {function}. 1401 // Get the "prototype" (or initial map) of the {function}.
1410 __ LoadP(function_prototype, 1402 __ LoadP(function_prototype,
1411 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 1403 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1412 __ AssertNotSmi(function_prototype); 1404 __ AssertNotSmi(function_prototype);
1413 1405
1414 // Resolve the prototype if the {function} has an initial map. Afterwards the 1406 // Resolve the prototype if the {function} has an initial map. Afterwards the
1415 // {function_prototype} will be either the JSReceiver prototype object or the 1407 // {function_prototype} will be either the JSReceiver prototype object or the
1416 // hole value, which means that no instances of the {function} were created so 1408 // hole value, which means that no instances of the {function} were created so
1417 // far and hence we should return false. 1409 // far and hence we should return false.
1418 Label function_prototype_valid; 1410 Label function_prototype_valid;
1419 __ CompareObjectType(function_prototype, scratch, scratch, MAP_TYPE); 1411 __ CompareObjectType(function_prototype, scratch, scratch, MAP_TYPE);
1420 __ bne(&function_prototype_valid); 1412 __ bne(&function_prototype_valid);
1421 __ LoadP(function_prototype, 1413 __ LoadP(function_prototype,
1422 FieldMemOperand(function_prototype, Map::kPrototypeOffset)); 1414 FieldMemOperand(function_prototype, Map::kPrototypeOffset));
1423 __ bind(&function_prototype_valid); 1415 __ bind(&function_prototype_valid);
1424 __ AssertNotSmi(function_prototype); 1416 __ AssertNotSmi(function_prototype);
1425 1417
1426 // Update the global instanceof cache with the current {object} map and 1418 // Update the global instanceof cache with the current {object} map and
1427 // {function}. The cached answer will be set when it is known below. 1419 // {function}. The cached answer will be set when it is known below.
1428 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 1420 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
1429 __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex); 1421 __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
1430 1422
1431 // Loop through the prototype chain looking for the {function} prototype. 1423 // Loop through the prototype chain looking for the {function} prototype.
1432 // Assume true, and change to false if not found. 1424 // Assume true, and change to false if not found.
1433 Register const object_instance_type = function_map; 1425 Register const object_instance_type = function_map;
1434 Register const map_bit_field = function_map; 1426 Register const map_bit_field = function_map;
1435 Register const null = scratch; 1427 Register const null = scratch;
1436 Register const result = r3; 1428 Register const result = r2;
1437 1429
1438 Label done, loop, fast_runtime_fallback; 1430 Label done, loop, fast_runtime_fallback;
1439 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1431 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1440 __ LoadRoot(null, Heap::kNullValueRootIndex); 1432 __ LoadRoot(null, Heap::kNullValueRootIndex);
1441 __ bind(&loop); 1433 __ bind(&loop);
1442 1434
1443 // Check if the object needs to be access checked. 1435 // Check if the object needs to be access checked.
1444 __ lbz(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset)); 1436 __ LoadlB(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
1445 __ TestBit(map_bit_field, Map::kIsAccessCheckNeeded, r0); 1437 __ TestBit(map_bit_field, Map::kIsAccessCheckNeeded, r0);
1446 __ bne(&fast_runtime_fallback, cr0); 1438 __ bne(&fast_runtime_fallback);
1447 // Check if the current object is a Proxy. 1439 // Check if the current object is a Proxy.
1448 __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE); 1440 __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
1449 __ beq(&fast_runtime_fallback); 1441 __ beq(&fast_runtime_fallback);
1450 1442
1451 __ LoadP(object, FieldMemOperand(object_map, Map::kPrototypeOffset)); 1443 __ LoadP(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
1452 __ cmp(object, function_prototype); 1444 __ CmpP(object, function_prototype);
1453 __ beq(&done); 1445 __ beq(&done);
1454 __ cmp(object, null); 1446 __ CmpP(object, null);
1455 __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); 1447 __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
1456 __ bne(&loop); 1448 __ bne(&loop);
1457 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1449 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1458 __ bind(&done); 1450 __ bind(&done);
1459 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex); 1451 __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
1460 __ Ret(); 1452 __ Ret();
1461 1453
1462 // Found Proxy or access check needed: Call the runtime 1454 // Found Proxy or access check needed: Call the runtime
1463 __ bind(&fast_runtime_fallback); 1455 __ bind(&fast_runtime_fallback);
1464 __ Push(object, function_prototype); 1456 __ Push(object, function_prototype);
1465 // Invalidate the instanceof cache. 1457 // Invalidate the instanceof cache.
1466 __ LoadSmiLiteral(scratch, Smi::FromInt(0)); 1458 __ LoadSmiLiteral(scratch, Smi::FromInt(0));
1467 __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex); 1459 __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex);
1468 __ TailCallRuntime(Runtime::kHasInPrototypeChain); 1460 __ TailCallRuntime(Runtime::kHasInPrototypeChain);
1469 1461
1470 // Slow-case: Call the %InstanceOf runtime function. 1462 // Slow-case: Call the %InstanceOf runtime function.
1471 __ bind(&slow_case); 1463 __ bind(&slow_case);
1472 __ Push(object, function); 1464 __ Push(object, function);
1473 __ TailCallRuntime(Runtime::kInstanceOf); 1465 __ TailCallRuntime(Runtime::kInstanceOf);
1474 } 1466 }
1475 1467
1476
1477 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { 1468 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
1478 Label miss; 1469 Label miss;
1479 Register receiver = LoadDescriptor::ReceiverRegister(); 1470 Register receiver = LoadDescriptor::ReceiverRegister();
1480 // Ensure that the vector and slot registers won't be clobbered before 1471 // Ensure that the vector and slot registers won't be clobbered before
1481 // calling the miss handler. 1472 // calling the miss handler.
1482 DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::VectorRegister(), 1473 DCHECK(!AreAliased(r6, r7, LoadWithVectorDescriptor::VectorRegister(),
1483 LoadWithVectorDescriptor::SlotRegister())); 1474 LoadWithVectorDescriptor::SlotRegister()));
1484 1475
1485 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r7, 1476 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r6,
1486 r8, &miss); 1477 r7, &miss);
1487 __ bind(&miss); 1478 __ bind(&miss);
1488 PropertyAccessCompiler::TailCallBuiltin( 1479 PropertyAccessCompiler::TailCallBuiltin(
1489 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); 1480 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
1490 } 1481 }
1491 1482
1492
1493 void LoadIndexedStringStub::Generate(MacroAssembler* masm) { 1483 void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
1494 // Return address is in lr. 1484 // Return address is in lr.
1495 Label miss; 1485 Label miss;
1496 1486
1497 Register receiver = LoadDescriptor::ReceiverRegister(); 1487 Register receiver = LoadDescriptor::ReceiverRegister();
1498 Register index = LoadDescriptor::NameRegister(); 1488 Register index = LoadDescriptor::NameRegister();
1499 Register scratch = r8; 1489 Register scratch = r7;
1500 Register result = r3; 1490 Register result = r2;
1501 DCHECK(!scratch.is(receiver) && !scratch.is(index)); 1491 DCHECK(!scratch.is(receiver) && !scratch.is(index));
1502 DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) && 1492 DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
1503 result.is(LoadWithVectorDescriptor::SlotRegister())); 1493 result.is(LoadWithVectorDescriptor::SlotRegister()));
1504 1494
1505 // StringCharAtGenerator doesn't use the result register until it's passed 1495 // StringCharAtGenerator doesn't use the result register until it's passed
1506 // the different miss possibilities. If it did, we would have a conflict 1496 // the different miss possibilities. If it did, we would have a conflict
1507 // when FLAG_vector_ics is true. 1497 // when FLAG_vector_ics is true.
1508 StringCharAtGenerator char_at_generator(receiver, index, scratch, result, 1498 StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
1509 &miss, // When not a string. 1499 &miss, // When not a string.
1510 &miss, // When not a number. 1500 &miss, // When not a number.
1511 &miss, // When index out of range. 1501 &miss, // When index out of range.
1512 STRING_INDEX_IS_ARRAY_INDEX, 1502 STRING_INDEX_IS_ARRAY_INDEX,
1513 RECEIVER_IS_STRING); 1503 RECEIVER_IS_STRING);
1514 char_at_generator.GenerateFast(masm); 1504 char_at_generator.GenerateFast(masm);
1515 __ Ret(); 1505 __ Ret();
1516 1506
1517 StubRuntimeCallHelper call_helper; 1507 StubRuntimeCallHelper call_helper;
1518 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); 1508 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
1519 1509
1520 __ bind(&miss); 1510 __ bind(&miss);
1521 PropertyAccessCompiler::TailCallBuiltin( 1511 PropertyAccessCompiler::TailCallBuiltin(
1522 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); 1512 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
1523 } 1513 }
1524 1514
1525
1526 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { 1515 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
1527 // Return address is in lr. 1516 // Return address is in lr.
1528 Label slow; 1517 Label slow;
1529 1518
1530 Register receiver = LoadDescriptor::ReceiverRegister(); 1519 Register receiver = LoadDescriptor::ReceiverRegister();
1531 Register key = LoadDescriptor::NameRegister(); 1520 Register key = LoadDescriptor::NameRegister();
1532 1521
1533 // Check that the key is an array index, that is Uint32. 1522 // Check that the key is an array index, that is Uint32.
1534 __ TestIfPositiveSmi(key, r0); 1523 __ TestIfPositiveSmi(key, r0);
1535 __ bne(&slow, cr0); 1524 __ bne(&slow);
1536 1525
1537 // Everything is fine, call runtime. 1526 // Everything is fine, call runtime.
1538 __ Push(receiver, key); // Receiver, key. 1527 __ Push(receiver, key); // Receiver, key.
1539 1528
1540 // Perform tail call to the entry. 1529 // Perform tail call to the entry.
1541 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor); 1530 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor);
1542 1531
1543 __ bind(&slow); 1532 __ bind(&slow);
1544 PropertyAccessCompiler::TailCallBuiltin( 1533 PropertyAccessCompiler::TailCallBuiltin(
1545 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); 1534 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
1546 } 1535 }
1547 1536
1548
1549 void RegExpExecStub::Generate(MacroAssembler* masm) { 1537 void RegExpExecStub::Generate(MacroAssembler* masm) {
1550 // Just jump directly to runtime if native RegExp is not selected at compile 1538 // Just jump directly to runtime if native RegExp is not selected at compile
1551 // time or if regexp entry in generated code is turned off runtime switch or 1539 // time or if regexp entry in generated code is turned off runtime switch or
1552 // at compilation. 1540 // at compilation.
1553 #ifdef V8_INTERPRETED_REGEXP 1541 #ifdef V8_INTERPRETED_REGEXP
1554 __ TailCallRuntime(Runtime::kRegExpExec); 1542 __ TailCallRuntime(Runtime::kRegExpExec);
1555 #else // V8_INTERPRETED_REGEXP 1543 #else // V8_INTERPRETED_REGEXP
1556 1544
1557 // Stack frame on entry. 1545 // Stack frame on entry.
1558 // sp[0]: last_match_info (expected JSArray) 1546 // sp[0]: last_match_info (expected JSArray)
1559 // sp[4]: previous index 1547 // sp[4]: previous index
1560 // sp[8]: subject string 1548 // sp[8]: subject string
1561 // sp[12]: JSRegExp object 1549 // sp[12]: JSRegExp object
1562 1550
1563 const int kLastMatchInfoOffset = 0 * kPointerSize; 1551 const int kLastMatchInfoOffset = 0 * kPointerSize;
1564 const int kPreviousIndexOffset = 1 * kPointerSize; 1552 const int kPreviousIndexOffset = 1 * kPointerSize;
1565 const int kSubjectOffset = 2 * kPointerSize; 1553 const int kSubjectOffset = 2 * kPointerSize;
1566 const int kJSRegExpOffset = 3 * kPointerSize; 1554 const int kJSRegExpOffset = 3 * kPointerSize;
1567 1555
1568 Label runtime, br_over, encoding_type_UC16; 1556 Label runtime, br_over, encoding_type_UC16;
1569 1557
1570 // Allocation of registers for this function. These are in callee save 1558 // Allocation of registers for this function. These are in callee save
1571 // registers and will be preserved by the call to the native RegExp code, as 1559 // registers and will be preserved by the call to the native RegExp code, as
1572 // this code is called using the normal C calling convention. When calling 1560 // this code is called using the normal C calling convention. When calling
1573 // directly from generated code the native RegExp code will not do a GC and 1561 // directly from generated code the native RegExp code will not do a GC and
1574 // therefore the content of these registers are safe to use after the call. 1562 // therefore the content of these registers are safe to use after the call.
1575 Register subject = r14; 1563 Register subject = r6;
1576 Register regexp_data = r15; 1564 Register regexp_data = r7;
1577 Register last_match_info_elements = r16; 1565 Register last_match_info_elements = r8;
1578 Register code = r17; 1566 Register code = r9;
1567
1568 __ CleanseP(r14);
1579 1569
1580 // Ensure register assigments are consistent with callee save masks 1570 // Ensure register assigments are consistent with callee save masks
1581 DCHECK(subject.bit() & kCalleeSaved); 1571 DCHECK(subject.bit() & kCalleeSaved);
1582 DCHECK(regexp_data.bit() & kCalleeSaved); 1572 DCHECK(regexp_data.bit() & kCalleeSaved);
1583 DCHECK(last_match_info_elements.bit() & kCalleeSaved); 1573 DCHECK(last_match_info_elements.bit() & kCalleeSaved);
1584 DCHECK(code.bit() & kCalleeSaved); 1574 DCHECK(code.bit() & kCalleeSaved);
1585 1575
1586 // Ensure that a RegExp stack is allocated. 1576 // Ensure that a RegExp stack is allocated.
1587 ExternalReference address_of_regexp_stack_memory_address = 1577 ExternalReference address_of_regexp_stack_memory_address =
1588 ExternalReference::address_of_regexp_stack_memory_address(isolate()); 1578 ExternalReference::address_of_regexp_stack_memory_address(isolate());
1589 ExternalReference address_of_regexp_stack_memory_size = 1579 ExternalReference address_of_regexp_stack_memory_size =
1590 ExternalReference::address_of_regexp_stack_memory_size(isolate()); 1580 ExternalReference::address_of_regexp_stack_memory_size(isolate());
1591 __ mov(r3, Operand(address_of_regexp_stack_memory_size)); 1581 __ mov(r2, Operand(address_of_regexp_stack_memory_size));
1592 __ LoadP(r3, MemOperand(r3, 0)); 1582 __ LoadAndTestP(r2, MemOperand(r2));
1593 __ cmpi(r3, Operand::Zero());
1594 __ beq(&runtime); 1583 __ beq(&runtime);
1595 1584
1596 // Check that the first argument is a JSRegExp object. 1585 // Check that the first argument is a JSRegExp object.
1597 __ LoadP(r3, MemOperand(sp, kJSRegExpOffset)); 1586 __ LoadP(r2, MemOperand(sp, kJSRegExpOffset));
1598 __ JumpIfSmi(r3, &runtime); 1587 __ JumpIfSmi(r2, &runtime);
1599 __ CompareObjectType(r3, r4, r4, JS_REGEXP_TYPE); 1588 __ CompareObjectType(r2, r3, r3, JS_REGEXP_TYPE);
1600 __ bne(&runtime); 1589 __ bne(&runtime);
1601 1590
1602 // Check that the RegExp has been compiled (data contains a fixed array). 1591 // Check that the RegExp has been compiled (data contains a fixed array).
1603 __ LoadP(regexp_data, FieldMemOperand(r3, JSRegExp::kDataOffset)); 1592 __ LoadP(regexp_data, FieldMemOperand(r2, JSRegExp::kDataOffset));
1604 if (FLAG_debug_code) { 1593 if (FLAG_debug_code) {
1605 __ TestIfSmi(regexp_data, r0); 1594 __ TestIfSmi(regexp_data);
1606 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected, cr0); 1595 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected, cr0);
1607 __ CompareObjectType(regexp_data, r3, r3, FIXED_ARRAY_TYPE); 1596 __ CompareObjectType(regexp_data, r2, r2, FIXED_ARRAY_TYPE);
1608 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); 1597 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
1609 } 1598 }
1610 1599
1611 // regexp_data: RegExp data (FixedArray) 1600 // regexp_data: RegExp data (FixedArray)
1612 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 1601 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
1613 __ LoadP(r3, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 1602 __ LoadP(r2, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
1614 // DCHECK(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu); 1603 // DCHECK(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu);
1615 __ CmpSmiLiteral(r3, Smi::FromInt(JSRegExp::IRREGEXP), r0); 1604 __ CmpSmiLiteral(r2, Smi::FromInt(JSRegExp::IRREGEXP), r0);
1616 __ bne(&runtime); 1605 __ bne(&runtime);
1617 1606
1618 // regexp_data: RegExp data (FixedArray) 1607 // regexp_data: RegExp data (FixedArray)
1619 // Check that the number of captures fit in the static offsets vector buffer. 1608 // Check that the number of captures fit in the static offsets vector buffer.
1620 __ LoadP(r5, 1609 __ LoadP(r4,
1621 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 1610 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1622 // Check (number_of_captures + 1) * 2 <= offsets vector size 1611 // Check (number_of_captures + 1) * 2 <= offsets vector size
1623 // Or number_of_captures * 2 <= offsets vector size - 2 1612 // Or number_of_captures * 2 <= offsets vector size - 2
1624 // SmiToShortArrayOffset accomplishes the multiplication by 2 and 1613 // SmiToShortArrayOffset accomplishes the multiplication by 2 and
1625 // SmiUntag (which is a nop for 32-bit). 1614 // SmiUntag (which is a nop for 32-bit).
1626 __ SmiToShortArrayOffset(r5, r5); 1615 __ SmiToShortArrayOffset(r4, r4);
1627 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 1616 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
1628 __ cmpli(r5, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); 1617 __ CmpLogicalP(r4, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
1629 __ bgt(&runtime); 1618 __ bgt(&runtime);
1630 1619
1631 // Reset offset for possibly sliced string. 1620 // Reset offset for possibly sliced string.
1632 __ li(r11, Operand::Zero()); 1621 __ LoadImmP(ip, Operand::Zero());
1633 __ LoadP(subject, MemOperand(sp, kSubjectOffset)); 1622 __ LoadP(subject, MemOperand(sp, kSubjectOffset));
1634 __ JumpIfSmi(subject, &runtime); 1623 __ JumpIfSmi(subject, &runtime);
1635 __ mr(r6, subject); // Make a copy of the original subject string. 1624 __ LoadRR(r5, subject); // Make a copy of the original subject string.
1636 __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); 1625 __ LoadP(r2, FieldMemOperand(subject, HeapObject::kMapOffset));
1637 __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); 1626 __ LoadlB(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
1638 // subject: subject string 1627 // subject: subject string
1639 // r6: subject string 1628 // r5: subject string
1640 // r3: subject string instance type 1629 // r2: subject string instance type
1641 // regexp_data: RegExp data (FixedArray) 1630 // regexp_data: RegExp data (FixedArray)
1642 // Handle subject string according to its encoding and representation: 1631 // Handle subject string according to its encoding and representation:
1643 // (1) Sequential string? If yes, go to (5). 1632 // (1) Sequential string? If yes, go to (5).
1644 // (2) Anything but sequential or cons? If yes, go to (6). 1633 // (2) Anything but sequential or cons? If yes, go to (6).
1645 // (3) Cons string. If the string is flat, replace subject with first string. 1634 // (3) Cons string. If the string is flat, replace subject with first string.
1646 // Otherwise bailout. 1635 // Otherwise bailout.
1647 // (4) Is subject external? If yes, go to (7). 1636 // (4) Is subject external? If yes, go to (7).
1648 // (5) Sequential string. Load regexp code according to encoding. 1637 // (5) Sequential string. Load regexp code according to encoding.
1649 // (E) Carry on. 1638 // (E) Carry on.
1650 /// [...] 1639 /// [...]
1651 1640
1652 // Deferred code at the end of the stub: 1641 // Deferred code at the end of the stub:
1653 // (6) Not a long external string? If yes, go to (8). 1642 // (6) Not a long external string? If yes, go to (8).
1654 // (7) External string. Make it, offset-wise, look like a sequential string. 1643 // (7) External string. Make it, offset-wise, look like a sequential string.
1655 // Go to (5). 1644 // Go to (5).
1656 // (8) Short external string or not a string? If yes, bail out to runtime. 1645 // (8) Short external string or not a string? If yes, bail out to runtime.
1657 // (9) Sliced string. Replace subject with parent. Go to (4). 1646 // (9) Sliced string. Replace subject with parent. Go to (4).
1658 1647
1659 Label seq_string /* 5 */, external_string /* 7 */, check_underlying /* 4 */, 1648 Label seq_string /* 5 */, external_string /* 7 */, check_underlying /* 4 */,
1660 not_seq_nor_cons /* 6 */, not_long_external /* 8 */; 1649 not_seq_nor_cons /* 6 */, not_long_external /* 8 */;
1661 1650
1662 // (1) Sequential string? If yes, go to (5). 1651 // (1) Sequential string? If yes, go to (5).
1663 STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask | 1652 STATIC_ASSERT((kIsNotStringMask | kStringRepresentationMask |
1664 kShortExternalStringMask) == 0x93); 1653 kShortExternalStringMask) == 0x93);
1665 __ andi(r4, r3, Operand(kIsNotStringMask | kStringRepresentationMask | 1654 __ mov(r3, Operand(kIsNotStringMask | kStringRepresentationMask |
1666 kShortExternalStringMask)); 1655 kShortExternalStringMask));
1656 __ AndP(r3, r2);
1667 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 1657 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
1668 __ beq(&seq_string, cr0); // Go to (5). 1658 __ beq(&seq_string); // Go to (5).
1669 1659
1670 // (2) Anything but sequential or cons? If yes, go to (6). 1660 // (2) Anything but sequential or cons? If yes, go to (6).
1671 STATIC_ASSERT(kConsStringTag < kExternalStringTag); 1661 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
1672 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 1662 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
1673 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 1663 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
1674 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 1664 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
1675 STATIC_ASSERT(kExternalStringTag < 0xffffu); 1665 STATIC_ASSERT(kExternalStringTag < 0xffffu);
1676 __ cmpi(r4, Operand(kExternalStringTag)); 1666 __ CmpP(r3, Operand(kExternalStringTag));
1677 __ bge(&not_seq_nor_cons); // Go to (6). 1667 __ bge(&not_seq_nor_cons); // Go to (6).
1678 1668
1679 // (3) Cons string. Check that it's flat. 1669 // (3) Cons string. Check that it's flat.
1680 // Replace subject with first string and reload instance type. 1670 // Replace subject with first string and reload instance type.
1681 __ LoadP(r3, FieldMemOperand(subject, ConsString::kSecondOffset)); 1671 __ LoadP(r2, FieldMemOperand(subject, ConsString::kSecondOffset));
1682 __ CompareRoot(r3, Heap::kempty_stringRootIndex); 1672 __ CompareRoot(r2, Heap::kempty_stringRootIndex);
1683 __ bne(&runtime); 1673 __ bne(&runtime);
1684 __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 1674 __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
1685 1675
1686 // (4) Is subject external? If yes, go to (7). 1676 // (4) Is subject external? If yes, go to (7).
1687 __ bind(&check_underlying); 1677 __ bind(&check_underlying);
1688 __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); 1678 __ LoadP(r2, FieldMemOperand(subject, HeapObject::kMapOffset));
1689 __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); 1679 __ LoadlB(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
1690 STATIC_ASSERT(kSeqStringTag == 0); 1680 STATIC_ASSERT(kSeqStringTag == 0);
1691 STATIC_ASSERT(kStringRepresentationMask == 3); 1681 STATIC_ASSERT(kStringRepresentationMask == 3);
1692 __ andi(r0, r3, Operand(kStringRepresentationMask)); 1682 __ tmll(r2, Operand(kStringRepresentationMask));
1693 // The underlying external string is never a short external string. 1683 // The underlying external string is never a short external string.
1694 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); 1684 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
1695 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); 1685 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
1696 __ bne(&external_string, cr0); // Go to (7). 1686 __ bne(&external_string); // Go to (7).
1697 1687
1698 // (5) Sequential string. Load regexp code according to encoding. 1688 // (5) Sequential string. Load regexp code according to encoding.
1699 __ bind(&seq_string); 1689 __ bind(&seq_string);
1700 // subject: sequential subject string (or look-alike, external string) 1690 // subject: sequential subject string (or look-alike, external string)
1701 // r6: original subject string 1691 // r5: original subject string
1702 // Load previous index and check range before r6 is overwritten. We have to 1692 // Load previous index and check range before r5 is overwritten. We have to
1703 // use r6 instead of subject here because subject might have been only made 1693 // use r5 instead of subject here because subject might have been only made
1704 // to look like a sequential string when it actually is an external string. 1694 // to look like a sequential string when it actually is an external string.
1705 __ LoadP(r4, MemOperand(sp, kPreviousIndexOffset)); 1695 __ LoadP(r3, MemOperand(sp, kPreviousIndexOffset));
1706 __ JumpIfNotSmi(r4, &runtime); 1696 __ JumpIfNotSmi(r3, &runtime);
1707 __ LoadP(r6, FieldMemOperand(r6, String::kLengthOffset)); 1697 __ LoadP(r5, FieldMemOperand(r5, String::kLengthOffset));
1708 __ cmpl(r6, r4); 1698 __ CmpLogicalP(r5, r3);
1709 __ ble(&runtime); 1699 __ ble(&runtime);
1710 __ SmiUntag(r4); 1700 __ SmiUntag(r3);
1711 1701
1712 STATIC_ASSERT(4 == kOneByteStringTag); 1702 STATIC_ASSERT(4 == kOneByteStringTag);
1713 STATIC_ASSERT(kTwoByteStringTag == 0); 1703 STATIC_ASSERT(kTwoByteStringTag == 0);
1714 STATIC_ASSERT(kStringEncodingMask == 4); 1704 STATIC_ASSERT(kStringEncodingMask == 4);
1715 __ ExtractBitMask(r6, r3, kStringEncodingMask, SetRC); 1705 __ ExtractBitMask(r5, r2, kStringEncodingMask, SetRC);
1716 __ beq(&encoding_type_UC16, cr0); 1706 __ beq(&encoding_type_UC16, Label::kNear);
1717 __ LoadP(code, 1707 __ LoadP(code,
1718 FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset)); 1708 FieldMemOperand(regexp_data, JSRegExp::kDataOneByteCodeOffset));
1719 __ b(&br_over); 1709 __ b(&br_over, Label::kNear);
1720 __ bind(&encoding_type_UC16); 1710 __ bind(&encoding_type_UC16);
1721 __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); 1711 __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
1722 __ bind(&br_over); 1712 __ bind(&br_over);
1723 1713
1724 // (E) Carry on. String handling is done. 1714 // (E) Carry on. String handling is done.
1725 // code: irregexp code 1715 // code: irregexp code
1726 // Check that the irregexp code has been generated for the actual string 1716 // Check that the irregexp code has been generated for the actual string
1727 // encoding. If it has, the field contains a code object otherwise it contains 1717 // encoding. If it has, the field contains a code object otherwise it contains
1728 // a smi (code flushing support). 1718 // a smi (code flushing support).
1729 __ JumpIfSmi(code, &runtime); 1719 __ JumpIfSmi(code, &runtime);
1730 1720
1731 // r4: previous index 1721 // r3: previous index
1732 // r6: encoding of subject string (1 if one_byte, 0 if two_byte); 1722 // r5: encoding of subject string (1 if one_byte, 0 if two_byte);
1733 // code: Address of generated regexp code 1723 // code: Address of generated regexp code
1734 // subject: Subject string 1724 // subject: Subject string
1735 // regexp_data: RegExp data (FixedArray) 1725 // regexp_data: RegExp data (FixedArray)
1736 // All checks done. Now push arguments for native regexp code. 1726 // All checks done. Now push arguments for native regexp code.
1737 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r3, r5); 1727 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r2, r4);
1738 1728
1739 // Isolates: note we add an additional parameter here (isolate pointer). 1729 // Isolates: note we add an additional parameter here (isolate pointer).
1740 const int kRegExpExecuteArguments = 10; 1730 const int kRegExpExecuteArguments = 10;
1741 const int kParameterRegisters = 8; 1731 const int kParameterRegisters = 5;
1742 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 1732 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
1743 1733
1744 // Stack pointer now points to cell where return address is to be written. 1734 // Stack pointer now points to cell where return address is to be written.
1745 // Arguments are before that on the stack or in registers. 1735 // Arguments are before that on the stack or in registers.
1746 1736
1747 // Argument 10 (in stack parameter area): Pass current isolate address. 1737 // Argument 10 (in stack parameter area): Pass current isolate address.
1748 __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); 1738 __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
1749 __ StoreP(r3, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize)); 1739 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
1740 4 * kPointerSize));
1750 1741
1751 // Argument 9 is a dummy that reserves the space used for 1742 // Argument 9 is a dummy that reserves the space used for
1752 // the return address added by the ExitFrame in native calls. 1743 // the return address added by the ExitFrame in native calls.
1744 __ mov(r2, Operand::Zero());
1745 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
1746 3 * kPointerSize));
1753 1747
1754 // Argument 8 (r10): Indicate that this is a direct call from JavaScript. 1748 // Argument 8: Indicate that this is a direct call from JavaScript.
1755 __ li(r10, Operand(1)); 1749 __ mov(r2, Operand(1));
1750 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
1751 2 * kPointerSize));
1756 1752
1757 // Argument 7 (r9): Start (high end) of backtracking stack memory area. 1753 // Argument 7: Start (high end) of backtracking stack memory area.
1758 __ mov(r3, Operand(address_of_regexp_stack_memory_address)); 1754 __ mov(r2, Operand(address_of_regexp_stack_memory_address));
1759 __ LoadP(r3, MemOperand(r3, 0)); 1755 __ LoadP(r2, MemOperand(r2, 0));
1760 __ mov(r5, Operand(address_of_regexp_stack_memory_size)); 1756 __ mov(r1, Operand(address_of_regexp_stack_memory_size));
1761 __ LoadP(r5, MemOperand(r5, 0)); 1757 __ LoadP(r1, MemOperand(r1, 0));
1762 __ add(r9, r3, r5); 1758 __ AddP(r2, r1);
1759 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
1760 1 * kPointerSize));
1763 1761
1764 // Argument 6 (r8): Set the number of capture registers to zero to force 1762 // Argument 6: Set the number of capture registers to zero to force
1765 // global egexps to behave as non-global. This does not affect non-global 1763 // global egexps to behave as non-global. This does not affect non-global
1766 // regexps. 1764 // regexps.
1767 __ li(r8, Operand::Zero()); 1765 __ mov(r2, Operand::Zero());
1766 __ StoreP(r2, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
1767 0 * kPointerSize));
1768 1768
1769 // Argument 5 (r7): static offsets vector buffer. 1769 // Argument 1 (r2): Subject string.
1770 // Load the length from the original subject string from the previous stack
1771 // frame. Therefore we have to use fp, which points exactly to 15 pointer
1772 // sizes below the previous sp. (Because creating a new stack frame pushes
1773 // the previous fp onto the stack and moves up sp by 2 * kPointerSize and
1774 // 13 registers saved on the stack previously)
1775 __ LoadP(r2, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
1776
1777 // Argument 2 (r3): Previous index.
1778 // Already there
1779 __ AddP(r1, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
1780
1781 // Argument 5 (r6): static offsets vector buffer.
1770 __ mov( 1782 __ mov(
1771 r7, 1783 r6,
1772 Operand(ExternalReference::address_of_static_offsets_vector(isolate()))); 1784 Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
1773 1785
1774 // For arguments 4 (r6) and 3 (r5) get string length, calculate start of data 1786 // For arguments 4 (r5) and 3 (r4) get string length, calculate start of data
1775 // and calculate the shift of the index (0 for one-byte and 1 for two-byte). 1787 // and calculate the shift of the index (0 for one-byte and 1 for two byte).
1776 __ addi(r18, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 1788 __ XorP(r5, Operand(1));
1777 __ xori(r6, r6, Operand(1));
1778 // Load the length from the original subject string from the previous stack
1779 // frame. Therefore we have to use fp, which points exactly to two pointer
1780 // sizes below the previous sp. (Because creating a new stack frame pushes
1781 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
1782 __ LoadP(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
1783 // If slice offset is not 0, load the length from the original sliced string. 1789 // If slice offset is not 0, load the length from the original sliced string.
1784 // Argument 4, r6: End of string data 1790 // Argument 3, r4: Start of string data
1785 // Argument 3, r5: Start of string data
1786 // Prepare start and end index of the input. 1791 // Prepare start and end index of the input.
1787 __ ShiftLeft_(r11, r11, r6); 1792 __ ShiftLeftP(ip, ip, r5);
1788 __ add(r11, r18, r11); 1793 __ AddP(ip, r1, ip);
1789 __ ShiftLeft_(r5, r4, r6); 1794 __ ShiftLeftP(r4, r3, r5);
1790 __ add(r5, r11, r5); 1795 __ AddP(r4, ip, r4);
1791 1796
1792 __ LoadP(r18, FieldMemOperand(subject, String::kLengthOffset)); 1797 // Argument 4, r5: End of string data
1793 __ SmiUntag(r18); 1798 __ LoadP(r1, FieldMemOperand(r2, String::kLengthOffset));
1794 __ ShiftLeft_(r6, r18, r6); 1799 __ SmiUntag(r1);
1795 __ add(r6, r11, r6); 1800 __ ShiftLeftP(r0, r1, r5);
1796 1801 __ AddP(r5, ip, r0);
1797 // Argument 2 (r4): Previous index.
1798 // Already there
1799
1800 // Argument 1 (r3): Subject string.
1801 __ mr(r3, subject);
1802 1802
1803 // Locate the code entry and call it. 1803 // Locate the code entry and call it.
1804 __ addi(code, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 1804 __ AddP(code, Operand(Code::kHeaderSize - kHeapObjectTag));
1805 1805
1806 DirectCEntryStub stub(isolate()); 1806 DirectCEntryStub stub(isolate());
1807 stub.GenerateCall(masm, code); 1807 stub.GenerateCall(masm, code);
1808 1808
1809 __ LeaveExitFrame(false, no_reg, true); 1809 __ LeaveExitFrame(false, no_reg, true);
1810 1810
1811 // r3: result (int32) 1811 // r2: result (int32)
1812 // subject: subject string (callee saved) 1812 // subject: subject string -- needed to reload
1813 __ LoadP(subject, MemOperand(sp, kSubjectOffset));
1814
1813 // regexp_data: RegExp data (callee saved) 1815 // regexp_data: RegExp data (callee saved)
1814 // last_match_info_elements: Last match info elements (callee saved) 1816 // last_match_info_elements: Last match info elements (callee saved)
1815 // Check the result. 1817 // Check the result.
1816 Label success; 1818 Label success;
1817 __ cmpwi(r3, Operand(1)); 1819 __ Cmp32(r2, Operand(1));
1818 // We expect exactly one result since we force the called regexp to behave 1820 // We expect exactly one result since we force the called regexp to behave
1819 // as non-global. 1821 // as non-global.
1820 __ beq(&success); 1822 __ beq(&success);
1821 Label failure; 1823 Label failure;
1822 __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::FAILURE)); 1824 __ Cmp32(r2, Operand(NativeRegExpMacroAssembler::FAILURE));
1823 __ beq(&failure); 1825 __ beq(&failure);
1824 __ cmpwi(r3, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 1826 __ Cmp32(r2, Operand(NativeRegExpMacroAssembler::EXCEPTION));
1825 // If not exception it can only be retry. Handle that in the runtime system. 1827 // If not exception it can only be retry. Handle that in the runtime system.
1826 __ bne(&runtime); 1828 __ bne(&runtime);
1827 // Result must now be exception. If there is no pending exception already a 1829 // Result must now be exception. If there is no pending exception already a
1828 // stack overflow (on the backtrack stack) was detected in RegExp code but 1830 // stack overflow (on the backtrack stack) was detected in RegExp code but
1829 // haven't created the exception yet. Handle that in the runtime system. 1831 // haven't created the exception yet. Handle that in the runtime system.
1830 // TODO(592): Rerunning the RegExp to get the stack overflow exception. 1832 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
1831 __ mov(r4, Operand(isolate()->factory()->the_hole_value())); 1833 __ mov(r3, Operand(isolate()->factory()->the_hole_value()));
1832 __ mov(r5, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1834 __ mov(r4, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1833 isolate()))); 1835 isolate())));
1834 __ LoadP(r3, MemOperand(r5, 0)); 1836 __ LoadP(r2, MemOperand(r4, 0));
1835 __ cmp(r3, r4); 1837 __ CmpP(r2, r3);
1836 __ beq(&runtime); 1838 __ beq(&runtime);
1837 1839
1838 // For exception, throw the exception again. 1840 // For exception, throw the exception again.
1839 __ TailCallRuntime(Runtime::kRegExpExecReThrow); 1841 __ TailCallRuntime(Runtime::kRegExpExecReThrow);
1840 1842
1841 __ bind(&failure); 1843 __ bind(&failure);
1842 // For failure and exception return null. 1844 // For failure and exception return null.
1843 __ mov(r3, Operand(isolate()->factory()->null_value())); 1845 __ mov(r2, Operand(isolate()->factory()->null_value()));
1844 __ addi(sp, sp, Operand(4 * kPointerSize)); 1846 __ la(sp, MemOperand(sp, (4 * kPointerSize)));
1845 __ Ret(); 1847 __ Ret();
1846 1848
1847 // Process the result from the native regexp code. 1849 // Process the result from the native regexp code.
1848 __ bind(&success); 1850 __ bind(&success);
1849 __ LoadP(r4, 1851 __ LoadP(r3,
1850 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 1852 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
1851 // Calculate number of capture registers (number_of_captures + 1) * 2. 1853 // Calculate number of capture registers (number_of_captures + 1) * 2.
1852 // SmiToShortArrayOffset accomplishes the multiplication by 2 and 1854 // SmiToShortArrayOffset accomplishes the multiplication by 2 and
1853 // SmiUntag (which is a nop for 32-bit). 1855 // SmiUntag (which is a nop for 32-bit).
1854 __ SmiToShortArrayOffset(r4, r4); 1856 __ SmiToShortArrayOffset(r3, r3);
1855 __ addi(r4, r4, Operand(2)); 1857 __ AddP(r3, Operand(2));
1856 1858
1857 __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset)); 1859 __ LoadP(r2, MemOperand(sp, kLastMatchInfoOffset));
1858 __ JumpIfSmi(r3, &runtime); 1860 __ JumpIfSmi(r2, &runtime);
1859 __ CompareObjectType(r3, r5, r5, JS_ARRAY_TYPE); 1861 __ CompareObjectType(r2, r4, r4, JS_ARRAY_TYPE);
1860 __ bne(&runtime); 1862 __ bne(&runtime);
1861 // Check that the JSArray is in fast case. 1863 // Check that the JSArray is in fast case.
1862 __ LoadP(last_match_info_elements, 1864 __ LoadP(last_match_info_elements,
1863 FieldMemOperand(r3, JSArray::kElementsOffset)); 1865 FieldMemOperand(r2, JSArray::kElementsOffset));
1864 __ LoadP(r3, 1866 __ LoadP(r2,
1865 FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 1867 FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
1866 __ CompareRoot(r3, Heap::kFixedArrayMapRootIndex); 1868 __ CompareRoot(r2, Heap::kFixedArrayMapRootIndex);
1867 __ bne(&runtime); 1869 __ bne(&runtime);
1868 // Check that the last match info has space for the capture registers and the 1870 // Check that the last match info has space for the capture registers and the
1869 // additional information. 1871 // additional information.
1870 __ LoadP( 1872 __ LoadP(
1871 r3, FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 1873 r2, FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
1872 __ addi(r5, r4, Operand(RegExpImpl::kLastMatchOverhead)); 1874 __ AddP(r4, r3, Operand(RegExpImpl::kLastMatchOverhead));
1873 __ SmiUntag(r0, r3); 1875 __ SmiUntag(r0, r2);
1874 __ cmp(r5, r0); 1876 __ CmpP(r4, r0);
1875 __ bgt(&runtime); 1877 __ bgt(&runtime);
1876 1878
1877 // r4: number of capture registers 1879 // r3: number of capture registers
1878 // subject: subject string 1880 // subject: subject string
1879 // Store the capture count. 1881 // Store the capture count.
1880 __ SmiTag(r5, r4); 1882 __ SmiTag(r4, r3);
1881 __ StoreP(r5, FieldMemOperand(last_match_info_elements, 1883 __ StoreP(r4, FieldMemOperand(last_match_info_elements,
1882 RegExpImpl::kLastCaptureCountOffset), 1884 RegExpImpl::kLastCaptureCountOffset));
1883 r0);
1884 // Store last subject and last input. 1885 // Store last subject and last input.
1885 __ StoreP(subject, FieldMemOperand(last_match_info_elements, 1886 __ StoreP(subject, FieldMemOperand(last_match_info_elements,
1886 RegExpImpl::kLastSubjectOffset), 1887 RegExpImpl::kLastSubjectOffset));
1887 r0); 1888 __ LoadRR(r4, subject);
1888 __ mr(r5, subject);
1889 __ RecordWriteField(last_match_info_elements, RegExpImpl::kLastSubjectOffset, 1889 __ RecordWriteField(last_match_info_elements, RegExpImpl::kLastSubjectOffset,
1890 subject, r10, kLRHasNotBeenSaved, kDontSaveFPRegs); 1890 subject, r9, kLRHasNotBeenSaved, kDontSaveFPRegs);
1891 __ mr(subject, r5); 1891 __ LoadRR(subject, r4);
1892 __ StoreP(subject, FieldMemOperand(last_match_info_elements, 1892 __ StoreP(subject, FieldMemOperand(last_match_info_elements,
1893 RegExpImpl::kLastInputOffset), 1893 RegExpImpl::kLastInputOffset));
1894 r0);
1895 __ RecordWriteField(last_match_info_elements, RegExpImpl::kLastInputOffset, 1894 __ RecordWriteField(last_match_info_elements, RegExpImpl::kLastInputOffset,
1896 subject, r10, kLRHasNotBeenSaved, kDontSaveFPRegs); 1895 subject, r9, kLRHasNotBeenSaved, kDontSaveFPRegs);
1897 1896
1898 // Get the static offsets vector filled by the native regexp code. 1897 // Get the static offsets vector filled by the native regexp code.
1899 ExternalReference address_of_static_offsets_vector = 1898 ExternalReference address_of_static_offsets_vector =
1900 ExternalReference::address_of_static_offsets_vector(isolate()); 1899 ExternalReference::address_of_static_offsets_vector(isolate());
1901 __ mov(r5, Operand(address_of_static_offsets_vector)); 1900 __ mov(r4, Operand(address_of_static_offsets_vector));
1902 1901
1903 // r4: number of capture registers 1902 // r3: number of capture registers
1904 // r5: offsets vector 1903 // r4: offsets vector
1905 Label next_capture; 1904 Label next_capture;
1906 // Capture register counter starts from number of capture registers and 1905 // Capture register counter starts from number of capture registers and
1907 // counts down until wraping after zero. 1906 // counts down until wraping after zero.
1908 __ addi( 1907 __ AddP(
1909 r3, last_match_info_elements, 1908 r2, last_match_info_elements,
1910 Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag - kPointerSize)); 1909 Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag - kPointerSize));
1911 __ addi(r5, r5, Operand(-kIntSize)); // bias down for lwzu 1910 __ AddP(r4, Operand(-kIntSize)); // bias down for lwzu
1912 __ mtctr(r4);
1913 __ bind(&next_capture); 1911 __ bind(&next_capture);
1914 // Read the value from the static offsets vector buffer. 1912 // Read the value from the static offsets vector buffer.
1915 __ lwzu(r6, MemOperand(r5, kIntSize)); 1913 __ ly(r5, MemOperand(r4, kIntSize));
1914 __ lay(r4, MemOperand(r4, kIntSize));
1916 // Store the smi value in the last match info. 1915 // Store the smi value in the last match info.
1917 __ SmiTag(r6); 1916 __ SmiTag(r5);
1918 __ StorePU(r6, MemOperand(r3, kPointerSize)); 1917 __ StoreP(r5, MemOperand(r2, kPointerSize));
1919 __ bdnz(&next_capture); 1918 __ lay(r2, MemOperand(r2, kPointerSize));
1919 __ BranchOnCount(r3, &next_capture);
1920 1920
1921 // Return last match info. 1921 // Return last match info.
1922 __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset)); 1922 __ LoadP(r2, MemOperand(sp, kLastMatchInfoOffset));
1923 __ addi(sp, sp, Operand(4 * kPointerSize)); 1923 __ la(sp, MemOperand(sp, (4 * kPointerSize)));
1924 __ Ret(); 1924 __ Ret();
1925 1925
1926 // Do the runtime call to execute the regexp. 1926 // Do the runtime call to execute the regexp.
1927 __ bind(&runtime); 1927 __ bind(&runtime);
1928 __ TailCallRuntime(Runtime::kRegExpExec); 1928 __ TailCallRuntime(Runtime::kRegExpExec);
1929 1929
1930 // Deferred code for string handling. 1930 // Deferred code for string handling.
1931 // (6) Not a long external string? If yes, go to (8). 1931 // (6) Not a long external string? If yes, go to (8).
1932 __ bind(&not_seq_nor_cons); 1932 __ bind(&not_seq_nor_cons);
1933 // Compare flags are still set. 1933 // Compare flags are still set.
1934 __ bgt(&not_long_external); // Go to (8). 1934 __ bgt(&not_long_external); // Go to (8).
1935 1935
1936 // (7) External string. Make it, offset-wise, look like a sequential string. 1936 // (7) External string. Make it, offset-wise, look like a sequential string.
1937 __ bind(&external_string); 1937 __ bind(&external_string);
1938 __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset)); 1938 __ LoadP(r2, FieldMemOperand(subject, HeapObject::kMapOffset));
1939 __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); 1939 __ LoadlB(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
1940 if (FLAG_debug_code) { 1940 if (FLAG_debug_code) {
1941 // Assert that we do not have a cons or slice (indirect strings) here. 1941 // Assert that we do not have a cons or slice (indirect strings) here.
1942 // Sequential strings have already been ruled out. 1942 // Sequential strings have already been ruled out.
1943 STATIC_ASSERT(kIsIndirectStringMask == 1); 1943 STATIC_ASSERT(kIsIndirectStringMask == 1);
1944 __ andi(r0, r3, Operand(kIsIndirectStringMask)); 1944 __ tmll(r2, Operand(kIsIndirectStringMask));
1945 __ Assert(eq, kExternalStringExpectedButNotFound, cr0); 1945 __ Assert(eq, kExternalStringExpectedButNotFound, cr0);
1946 } 1946 }
1947 __ LoadP(subject, 1947 __ LoadP(subject,
1948 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 1948 FieldMemOperand(subject, ExternalString::kResourceDataOffset));
1949 // Move the pointer so that offset-wise, it looks like a sequential string. 1949 // Move the pointer so that offset-wise, it looks like a sequential string.
1950 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 1950 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
1951 __ subi(subject, subject, 1951 __ SubP(subject, subject,
1952 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 1952 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
1953 __ b(&seq_string); // Go to (5). 1953 __ b(&seq_string); // Go to (5).
1954 1954
1955 // (8) Short external string or not a string? If yes, bail out to runtime. 1955 // (8) Short external string or not a string? If yes, bail out to runtime.
1956 __ bind(&not_long_external); 1956 __ bind(&not_long_external);
1957 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0); 1957 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag != 0);
1958 __ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask)); 1958 __ mov(r0, Operand(kIsNotStringMask | kShortExternalStringMask));
1959 __ bne(&runtime, cr0); 1959 __ AndP(r0, r3);
1960 __ bne(&runtime);
1960 1961
1961 // (9) Sliced string. Replace subject with parent. Go to (4). 1962 // (9) Sliced string. Replace subject with parent. Go to (4).
1962 // Load offset into r11 and replace subject string with parent. 1963 // Load offset into ip and replace subject string with parent.
1963 __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset)); 1964 __ LoadP(ip, FieldMemOperand(subject, SlicedString::kOffsetOffset));
1964 __ SmiUntag(r11); 1965 __ SmiUntag(ip);
1965 __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); 1966 __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
1966 __ b(&check_underlying); // Go to (4). 1967 __ b(&check_underlying); // Go to (4).
1967 #endif // V8_INTERPRETED_REGEXP 1968 #endif // V8_INTERPRETED_REGEXP
1968 } 1969 }
1969 1970
1970
1971 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { 1971 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
1972 // r3 : number of arguments to the construct function 1972 // r2 : number of arguments to the construct function
1973 // r4 : the function to call 1973 // r3 : the function to call
1974 // r5 : feedback vector 1974 // r4 : feedback vector
1975 // r6 : slot in feedback vector (Smi) 1975 // r5 : slot in feedback vector (Smi)
1976 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 1976 FrameScope scope(masm, StackFrame::INTERNAL);
1977 1977
1978 // Number-of-arguments register must be smi-tagged to call out. 1978 // Number-of-arguments register must be smi-tagged to call out.
1979 __ SmiTag(r3); 1979 __ SmiTag(r2);
1980 __ Push(r6, r5, r4, r3); 1980 __ Push(r5, r4, r3, r2);
1981 1981
1982 __ CallStub(stub); 1982 __ CallStub(stub);
1983 1983
1984 __ Pop(r6, r5, r4, r3); 1984 __ Pop(r5, r4, r3, r2);
1985 __ SmiUntag(r3); 1985 __ SmiUntag(r2);
1986 } 1986 }
1987 1987
1988
1989 static void GenerateRecordCallTarget(MacroAssembler* masm) { 1988 static void GenerateRecordCallTarget(MacroAssembler* masm) {
1990 // Cache the called function in a feedback vector slot. Cache states 1989 // Cache the called function in a feedback vector slot. Cache states
1991 // are uninitialized, monomorphic (indicated by a JSFunction), and 1990 // are uninitialized, monomorphic (indicated by a JSFunction), and
1992 // megamorphic. 1991 // megamorphic.
1993 // r3 : number of arguments to the construct function 1992 // r2 : number of arguments to the construct function
1994 // r4 : the function to call 1993 // r3 : the function to call
1995 // r5 : feedback vector 1994 // r4 : feedback vector
1996 // r6 : slot in feedback vector (Smi) 1995 // r5 : slot in feedback vector (Smi)
1997 Label initialize, done, miss, megamorphic, not_array_function; 1996 Label initialize, done, miss, megamorphic, not_array_function;
1998 1997
1999 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), 1998 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
2000 masm->isolate()->heap()->megamorphic_symbol()); 1999 masm->isolate()->heap()->megamorphic_symbol());
2001 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), 2000 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()),
2002 masm->isolate()->heap()->uninitialized_symbol()); 2001 masm->isolate()->heap()->uninitialized_symbol());
2003 2002
2004 // Load the cache state into r8. 2003 // Load the cache state into r7.
2005 __ SmiToPtrArrayOffset(r8, r6); 2004 __ SmiToPtrArrayOffset(r7, r5);
2006 __ add(r8, r5, r8); 2005 __ AddP(r7, r4, r7);
2007 __ LoadP(r8, FieldMemOperand(r8, FixedArray::kHeaderSize)); 2006 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize));
2008 2007
2009 // A monomorphic cache hit or an already megamorphic state: invoke the 2008 // A monomorphic cache hit or an already megamorphic state: invoke the
2010 // function without changing the state. 2009 // function without changing the state.
2011 // We don't know if r8 is a WeakCell or a Symbol, but it's harmless to read at 2010 // We don't know if r7 is a WeakCell or a Symbol, but it's harmless to read at
2012 // this position in a symbol (see static asserts in type-feedback-vector.h). 2011 // this position in a symbol (see static asserts in type-feedback-vector.h).
2013 Label check_allocation_site; 2012 Label check_allocation_site;
2014 Register feedback_map = r9; 2013 Register feedback_map = r8;
2015 Register weak_value = r10; 2014 Register weak_value = r9;
2016 __ LoadP(weak_value, FieldMemOperand(r8, WeakCell::kValueOffset)); 2015 __ LoadP(weak_value, FieldMemOperand(r7, WeakCell::kValueOffset));
2017 __ cmp(r4, weak_value); 2016 __ CmpP(r3, weak_value);
2018 __ beq(&done); 2017 __ beq(&done);
2019 __ CompareRoot(r8, Heap::kmegamorphic_symbolRootIndex); 2018 __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex);
2020 __ beq(&done); 2019 __ beq(&done);
2021 __ LoadP(feedback_map, FieldMemOperand(r8, HeapObject::kMapOffset)); 2020 __ LoadP(feedback_map, FieldMemOperand(r7, HeapObject::kMapOffset));
2022 __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); 2021 __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex);
2023 __ bne(&check_allocation_site); 2022 __ bne(&check_allocation_site);
2024 2023
2025 // If the weak cell is cleared, we have a new chance to become monomorphic. 2024 // If the weak cell is cleared, we have a new chance to become monomorphic.
2026 __ JumpIfSmi(weak_value, &initialize); 2025 __ JumpIfSmi(weak_value, &initialize);
2027 __ b(&megamorphic); 2026 __ b(&megamorphic);
2028 2027
2029 __ bind(&check_allocation_site); 2028 __ bind(&check_allocation_site);
2030 // If we came here, we need to see if we are the array function. 2029 // If we came here, we need to see if we are the array function.
2031 // If we didn't have a matching function, and we didn't find the megamorph 2030 // If we didn't have a matching function, and we didn't find the megamorph
2032 // sentinel, then we have in the slot either some other function or an 2031 // sentinel, then we have in the slot either some other function or an
2033 // AllocationSite. 2032 // AllocationSite.
2034 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex); 2033 __ CompareRoot(feedback_map, Heap::kAllocationSiteMapRootIndex);
2035 __ bne(&miss); 2034 __ bne(&miss);
2036 2035
2037 // Make sure the function is the Array() function 2036 // Make sure the function is the Array() function
2038 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 2037 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r7);
2039 __ cmp(r4, r8); 2038 __ CmpP(r3, r7);
2040 __ bne(&megamorphic); 2039 __ bne(&megamorphic);
2041 __ b(&done); 2040 __ b(&done);
2042 2041
2043 __ bind(&miss); 2042 __ bind(&miss);
2044 2043
2045 // A monomorphic miss (i.e, here the cache is not uninitialized) goes 2044 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
2046 // megamorphic. 2045 // megamorphic.
2047 __ CompareRoot(r8, Heap::kuninitialized_symbolRootIndex); 2046 __ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex);
2048 __ beq(&initialize); 2047 __ beq(&initialize);
2049 // MegamorphicSentinel is an immortal immovable object (undefined) so no 2048 // MegamorphicSentinel is an immortal immovable object (undefined) so no
2050 // write-barrier is needed. 2049 // write-barrier is needed.
2051 __ bind(&megamorphic); 2050 __ bind(&megamorphic);
2052 __ SmiToPtrArrayOffset(r8, r6); 2051 __ SmiToPtrArrayOffset(r7, r5);
2053 __ add(r8, r5, r8); 2052 __ AddP(r7, r4, r7);
2054 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); 2053 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
2055 __ StoreP(ip, FieldMemOperand(r8, FixedArray::kHeaderSize), r0); 2054 __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0);
2056 __ jmp(&done); 2055 __ jmp(&done);
2057 2056
2058 // An uninitialized cache is patched with the function 2057 // An uninitialized cache is patched with the function
2059 __ bind(&initialize); 2058 __ bind(&initialize);
2060 2059
2061 // Make sure the function is the Array() function. 2060 // Make sure the function is the Array() function.
2062 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 2061 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r7);
2063 __ cmp(r4, r8); 2062 __ CmpP(r3, r7);
2064 __ bne(&not_array_function); 2063 __ bne(&not_array_function);
2065 2064
2066 // The target function is the Array constructor, 2065 // The target function is the Array constructor,
2067 // Create an AllocationSite if we don't already have it, store it in the 2066 // Create an AllocationSite if we don't already have it, store it in the
2068 // slot. 2067 // slot.
2069 CreateAllocationSiteStub create_stub(masm->isolate()); 2068 CreateAllocationSiteStub create_stub(masm->isolate());
2070 CallStubInRecordCallTarget(masm, &create_stub); 2069 CallStubInRecordCallTarget(masm, &create_stub);
2071 __ b(&done); 2070 __ b(&done);
2072 2071
2073 __ bind(&not_array_function); 2072 __ bind(&not_array_function);
2074 2073
2075 CreateWeakCellStub weak_cell_stub(masm->isolate()); 2074 CreateWeakCellStub weak_cell_stub(masm->isolate());
2076 CallStubInRecordCallTarget(masm, &weak_cell_stub); 2075 CallStubInRecordCallTarget(masm, &weak_cell_stub);
2077 __ bind(&done); 2076 __ bind(&done);
2078 } 2077 }
2079 2078
2080
2081 void CallConstructStub::Generate(MacroAssembler* masm) { 2079 void CallConstructStub::Generate(MacroAssembler* masm) {
2082 // r3 : number of arguments 2080 // r2 : number of arguments
2083 // r4 : the function to call 2081 // r3 : the function to call
2084 // r5 : feedback vector 2082 // r4 : feedback vector
2085 // r6 : slot in feedback vector (Smi, for RecordCallTarget) 2083 // r5 : slot in feedback vector (Smi, for RecordCallTarget)
2086 2084
2087 Label non_function; 2085 Label non_function;
2088 // Check that the function is not a smi. 2086 // Check that the function is not a smi.
2089 __ JumpIfSmi(r4, &non_function); 2087 __ JumpIfSmi(r3, &non_function);
2090 // Check that the function is a JSFunction. 2088 // Check that the function is a JSFunction.
2091 __ CompareObjectType(r4, r8, r8, JS_FUNCTION_TYPE); 2089 __ CompareObjectType(r3, r7, r7, JS_FUNCTION_TYPE);
2092 __ bne(&non_function); 2090 __ bne(&non_function);
2093 2091
2094 GenerateRecordCallTarget(masm); 2092 GenerateRecordCallTarget(masm);
2095 2093
2096 __ SmiToPtrArrayOffset(r8, r6); 2094 __ SmiToPtrArrayOffset(r7, r5);
2097 __ add(r8, r5, r8); 2095 __ AddP(r7, r4, r7);
2098 // Put the AllocationSite from the feedback vector into r5, or undefined. 2096 // Put the AllocationSite from the feedback vector into r4, or undefined.
2099 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize)); 2097 __ LoadP(r4, FieldMemOperand(r7, FixedArray::kHeaderSize));
2100 __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset)); 2098 __ LoadP(r7, FieldMemOperand(r4, AllocationSite::kMapOffset));
2101 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 2099 __ CompareRoot(r7, Heap::kAllocationSiteMapRootIndex);
2102 if (CpuFeatures::IsSupported(ISELECT)) { 2100 Label feedback_register_initialized;
2103 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); 2101 __ beq(&feedback_register_initialized);
2104 __ isel(eq, r5, r5, r8); 2102 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
2105 } else { 2103 __ bind(&feedback_register_initialized);
2106 Label feedback_register_initialized;
2107 __ beq(&feedback_register_initialized);
2108 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
2109 __ bind(&feedback_register_initialized);
2110 }
2111 2104
2112 __ AssertUndefinedOrAllocationSite(r5, r8); 2105 __ AssertUndefinedOrAllocationSite(r4, r7);
2113 2106
2114 // Pass function as new target. 2107 // Pass function as new target.
2115 __ mr(r6, r4); 2108 __ LoadRR(r5, r3);
2116 2109
2117 // Tail call to the function-specific construct stub (still in the caller 2110 // Tail call to the function-specific construct stub (still in the caller
2118 // context at this point). 2111 // context at this point).
2119 __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 2112 __ LoadP(r6, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
2120 __ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kConstructStubOffset)); 2113 __ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kConstructStubOffset));
2121 __ addi(ip, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); 2114 __ AddP(ip, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
2122 __ JumpToJSEntry(ip); 2115 __ JumpToJSEntry(ip);
2123 2116
2124 __ bind(&non_function); 2117 __ bind(&non_function);
2125 __ mr(r6, r4); 2118 __ LoadRR(r5, r3);
2126 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 2119 __ Jump(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
2127 } 2120 }
2128 2121
2129
2130 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) { 2122 void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
2131 // r4 - function 2123 // r3 - function
2132 // r6 - slot id 2124 // r5 - slot id
2133 // r5 - vector 2125 // r4 - vector
2134 // r7 - allocation site (loaded from vector[slot]) 2126 // r6 - allocation site (loaded from vector[slot])
2135 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8); 2127 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r7);
2136 __ cmp(r4, r8); 2128 __ CmpP(r3, r7);
2137 __ bne(miss); 2129 __ bne(miss);
2138 2130
2139 __ mov(r3, Operand(arg_count())); 2131 __ mov(r2, Operand(arg_count()));
2140 2132
2141 // Increment the call count for monomorphic function calls. 2133 // Increment the call count for monomorphic function calls.
2142 const int count_offset = FixedArray::kHeaderSize + kPointerSize; 2134 const int count_offset = FixedArray::kHeaderSize + kPointerSize;
2143 __ SmiToPtrArrayOffset(r8, r6); 2135 __ SmiToPtrArrayOffset(r7, r5);
2144 __ add(r5, r5, r8); 2136 __ AddP(r4, r4, r7);
2145 __ LoadP(r6, FieldMemOperand(r5, count_offset)); 2137 __ LoadP(r5, FieldMemOperand(r4, count_offset));
2146 __ AddSmiLiteral(r6, r6, Smi::FromInt(CallICNexus::kCallCountIncrement), r0); 2138 __ AddSmiLiteral(r5, r5, Smi::FromInt(CallICNexus::kCallCountIncrement), r0);
2147 __ StoreP(r6, FieldMemOperand(r5, count_offset), r0); 2139 __ StoreP(r5, FieldMemOperand(r4, count_offset), r0);
2148 2140
2149 __ mr(r5, r7); 2141 __ LoadRR(r4, r6);
2150 __ mr(r6, r4); 2142 __ LoadRR(r5, r3);
2151 ArrayConstructorStub stub(masm->isolate(), arg_count()); 2143 ArrayConstructorStub stub(masm->isolate(), arg_count());
2152 __ TailCallStub(&stub); 2144 __ TailCallStub(&stub);
2153 } 2145 }
2154 2146
2155
2156 void CallICStub::Generate(MacroAssembler* masm) { 2147 void CallICStub::Generate(MacroAssembler* masm) {
2157 // r4 - function 2148 // r3 - function
2158 // r6 - slot id (Smi) 2149 // r5 - slot id (Smi)
2159 // r5 - vector 2150 // r4 - vector
2160 Label extra_checks_or_miss, call, call_function; 2151 Label extra_checks_or_miss, call, call_function;
2161 int argc = arg_count(); 2152 int argc = arg_count();
2162 ParameterCount actual(argc); 2153 ParameterCount actual(argc);
2163 2154
2164 // The checks. First, does r4 match the recorded monomorphic target? 2155 // The checks. First, does r3 match the recorded monomorphic target?
2165 __ SmiToPtrArrayOffset(r9, r6); 2156 __ SmiToPtrArrayOffset(r8, r5);
2166 __ add(r9, r5, r9); 2157 __ AddP(r8, r4, r8);
2167 __ LoadP(r7, FieldMemOperand(r9, FixedArray::kHeaderSize)); 2158 __ LoadP(r6, FieldMemOperand(r8, FixedArray::kHeaderSize));
2168 2159
2169 // We don't know that we have a weak cell. We might have a private symbol 2160 // We don't know that we have a weak cell. We might have a private symbol
2170 // or an AllocationSite, but the memory is safe to examine. 2161 // or an AllocationSite, but the memory is safe to examine.
2171 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to 2162 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
2172 // FixedArray. 2163 // FixedArray.
2173 // WeakCell::kValueOffset - contains a JSFunction or Smi(0) 2164 // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
2174 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not 2165 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
2175 // computed, meaning that it can't appear to be a pointer. If the low bit is 2166 // computed, meaning that it can't appear to be a pointer. If the low bit is
2176 // 0, then hash is computed, but the 0 bit prevents the field from appearing 2167 // 0, then hash is computed, but the 0 bit prevents the field from appearing
2177 // to be a pointer. 2168 // to be a pointer.
2178 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); 2169 STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
2179 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == 2170 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
2180 WeakCell::kValueOffset && 2171 WeakCell::kValueOffset &&
2181 WeakCell::kValueOffset == Symbol::kHashFieldSlot); 2172 WeakCell::kValueOffset == Symbol::kHashFieldSlot);
2182 2173
2183 __ LoadP(r8, FieldMemOperand(r7, WeakCell::kValueOffset)); 2174 __ LoadP(r7, FieldMemOperand(r6, WeakCell::kValueOffset));
2184 __ cmp(r4, r8); 2175 __ CmpP(r3, r7);
2185 __ bne(&extra_checks_or_miss); 2176 __ bne(&extra_checks_or_miss, Label::kNear);
2186 2177
2187 // The compare above could have been a SMI/SMI comparison. Guard against this 2178 // The compare above could have been a SMI/SMI comparison. Guard against this
2188 // convincing us that we have a monomorphic JSFunction. 2179 // convincing us that we have a monomorphic JSFunction.
2189 __ JumpIfSmi(r4, &extra_checks_or_miss); 2180 __ JumpIfSmi(r3, &extra_checks_or_miss);
2190 2181
2191 // Increment the call count for monomorphic function calls. 2182 // Increment the call count for monomorphic function calls.
2192 const int count_offset = FixedArray::kHeaderSize + kPointerSize; 2183 const int count_offset = FixedArray::kHeaderSize + kPointerSize;
2193 __ LoadP(r6, FieldMemOperand(r9, count_offset)); 2184 __ LoadP(r5, FieldMemOperand(r8, count_offset));
2194 __ AddSmiLiteral(r6, r6, Smi::FromInt(CallICNexus::kCallCountIncrement), r0); 2185 __ AddSmiLiteral(r5, r5, Smi::FromInt(CallICNexus::kCallCountIncrement), r0);
2195 __ StoreP(r6, FieldMemOperand(r9, count_offset), r0); 2186 __ StoreP(r5, FieldMemOperand(r8, count_offset), r0);
2196 2187
2197 __ bind(&call_function); 2188 __ bind(&call_function);
2198 __ mov(r3, Operand(argc)); 2189 __ mov(r2, Operand(argc));
2199 __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(), 2190 __ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
2200 tail_call_mode()), 2191 tail_call_mode()),
2201 RelocInfo::CODE_TARGET); 2192 RelocInfo::CODE_TARGET);
2202 2193
2203 __ bind(&extra_checks_or_miss); 2194 __ bind(&extra_checks_or_miss);
2204 Label uninitialized, miss, not_allocation_site; 2195 Label uninitialized, miss, not_allocation_site;
2205 2196
2206 __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex); 2197 __ CompareRoot(r6, Heap::kmegamorphic_symbolRootIndex);
2207 __ beq(&call); 2198 __ beq(&call);
2208 2199
2209 // Verify that r7 contains an AllocationSite 2200 // Verify that r6 contains an AllocationSite
2210 __ LoadP(r8, FieldMemOperand(r7, HeapObject::kMapOffset)); 2201 __ LoadP(r7, FieldMemOperand(r6, HeapObject::kMapOffset));
2211 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 2202 __ CompareRoot(r7, Heap::kAllocationSiteMapRootIndex);
2212 __ bne(&not_allocation_site); 2203 __ bne(&not_allocation_site);
2213 2204
2214 // We have an allocation site. 2205 // We have an allocation site.
2215 HandleArrayCase(masm, &miss); 2206 HandleArrayCase(masm, &miss);
2216 2207
2217 __ bind(&not_allocation_site); 2208 __ bind(&not_allocation_site);
2218 2209
2219 // The following cases attempt to handle MISS cases without going to the 2210 // The following cases attempt to handle MISS cases without going to the
2220 // runtime. 2211 // runtime.
2221 if (FLAG_trace_ic) { 2212 if (FLAG_trace_ic) {
2222 __ b(&miss); 2213 __ b(&miss);
2223 } 2214 }
2224 2215
2225 __ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex); 2216 __ CompareRoot(r6, Heap::kuninitialized_symbolRootIndex);
2226 __ beq(&uninitialized); 2217 __ beq(&uninitialized);
2227 2218
2228 // We are going megamorphic. If the feedback is a JSFunction, it is fine 2219 // We are going megamorphic. If the feedback is a JSFunction, it is fine
2229 // to handle it here. More complex cases are dealt with in the runtime. 2220 // to handle it here. More complex cases are dealt with in the runtime.
2230 __ AssertNotSmi(r7); 2221 __ AssertNotSmi(r6);
2231 __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE); 2222 __ CompareObjectType(r6, r7, r7, JS_FUNCTION_TYPE);
2232 __ bne(&miss); 2223 __ bne(&miss);
2233 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex); 2224 __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
2234 __ StoreP(ip, FieldMemOperand(r9, FixedArray::kHeaderSize), r0); 2225 __ StoreP(ip, FieldMemOperand(r8, FixedArray::kHeaderSize), r0);
2235 2226
2236 __ bind(&call); 2227 __ bind(&call);
2237 __ mov(r3, Operand(argc)); 2228 __ mov(r2, Operand(argc));
2238 __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()), 2229 __ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
2239 RelocInfo::CODE_TARGET); 2230 RelocInfo::CODE_TARGET);
2240 2231
2241 __ bind(&uninitialized); 2232 __ bind(&uninitialized);
2242 2233
2243 // We are going monomorphic, provided we actually have a JSFunction. 2234 // We are going monomorphic, provided we actually have a JSFunction.
2244 __ JumpIfSmi(r4, &miss); 2235 __ JumpIfSmi(r3, &miss);
2245 2236
2246 // Goto miss case if we do not have a function. 2237 // Goto miss case if we do not have a function.
2247 __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE); 2238 __ CompareObjectType(r3, r6, r6, JS_FUNCTION_TYPE);
2248 __ bne(&miss); 2239 __ bne(&miss);
2249 2240
2250 // Make sure the function is not the Array() function, which requires special 2241 // Make sure the function is not the Array() function, which requires special
2251 // behavior on MISS. 2242 // behavior on MISS.
2252 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r7); 2243 __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r6);
2253 __ cmp(r4, r7); 2244 __ CmpP(r3, r6);
2254 __ beq(&miss); 2245 __ beq(&miss);
2255 2246
2256 // Make sure the function belongs to the same native context. 2247 // Make sure the function belongs to the same native context.
2257 __ LoadP(r7, FieldMemOperand(r4, JSFunction::kContextOffset)); 2248 __ LoadP(r6, FieldMemOperand(r3, JSFunction::kContextOffset));
2258 __ LoadP(r7, ContextMemOperand(r7, Context::NATIVE_CONTEXT_INDEX)); 2249 __ LoadP(r6, ContextMemOperand(r6, Context::NATIVE_CONTEXT_INDEX));
2259 __ LoadP(ip, NativeContextMemOperand()); 2250 __ LoadP(ip, NativeContextMemOperand());
2260 __ cmp(r7, ip); 2251 __ CmpP(r6, ip);
2261 __ bne(&miss); 2252 __ bne(&miss);
2262 2253
2263 // Initialize the call counter. 2254 // Initialize the call counter.
2264 __ LoadSmiLiteral(r8, Smi::FromInt(CallICNexus::kCallCountIncrement)); 2255 __ LoadSmiLiteral(r7, Smi::FromInt(CallICNexus::kCallCountIncrement));
2265 __ StoreP(r8, FieldMemOperand(r9, count_offset), r0); 2256 __ StoreP(r7, FieldMemOperand(r8, count_offset), r0);
2266 2257
2267 // Store the function. Use a stub since we need a frame for allocation. 2258 // Store the function. Use a stub since we need a frame for allocation.
2268 // r5 - vector 2259 // r4 - vector
2269 // r6 - slot 2260 // r5 - slot
2270 // r4 - function 2261 // r3 - function
2271 { 2262 {
2272 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2263 FrameScope scope(masm, StackFrame::INTERNAL);
2273 CreateWeakCellStub create_stub(masm->isolate()); 2264 CreateWeakCellStub create_stub(masm->isolate());
2274 __ Push(r4); 2265 __ Push(r3);
2275 __ CallStub(&create_stub); 2266 __ CallStub(&create_stub);
2276 __ Pop(r4); 2267 __ Pop(r3);
2277 } 2268 }
2278 2269
2279 __ b(&call_function); 2270 __ b(&call_function);
2280 2271
2281 // We are here because tracing is on or we encountered a MISS case we can't 2272 // We are here because tracing is on or we encountered a MISS case we can't
2282 // handle here. 2273 // handle here.
2283 __ bind(&miss); 2274 __ bind(&miss);
2284 GenerateMiss(masm); 2275 GenerateMiss(masm);
2285 2276
2286 __ b(&call); 2277 __ b(&call);
2287 } 2278 }
2288 2279
2289
2290 void CallICStub::GenerateMiss(MacroAssembler* masm) { 2280 void CallICStub::GenerateMiss(MacroAssembler* masm) {
2291 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2281 FrameScope scope(masm, StackFrame::INTERNAL);
2292 2282
2293 // Push the function and feedback info. 2283 // Push the function and feedback info.
2294 __ Push(r4, r5, r6); 2284 __ Push(r3, r4, r5);
2295 2285
2296 // Call the entry. 2286 // Call the entry.
2297 __ CallRuntime(Runtime::kCallIC_Miss); 2287 __ CallRuntime(Runtime::kCallIC_Miss);
2298 2288
2299 // Move result to r4 and exit the internal frame. 2289 // Move result to r3 and exit the internal frame.
2300 __ mr(r4, r3); 2290 __ LoadRR(r3, r2);
2301 } 2291 }
2302 2292
2303
2304 // StringCharCodeAtGenerator 2293 // StringCharCodeAtGenerator
2305 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 2294 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
2306 // If the receiver is a smi trigger the non-string case. 2295 // If the receiver is a smi trigger the non-string case.
2307 if (check_mode_ == RECEIVER_IS_UNKNOWN) { 2296 if (check_mode_ == RECEIVER_IS_UNKNOWN) {
2308 __ JumpIfSmi(object_, receiver_not_string_); 2297 __ JumpIfSmi(object_, receiver_not_string_);
2309 2298
2310 // Fetch the instance type of the receiver into result register. 2299 // Fetch the instance type of the receiver into result register.
2311 __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 2300 __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
2312 __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 2301 __ LoadlB(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
2313 // If the receiver is not a string trigger the non-string case. 2302 // If the receiver is not a string trigger the non-string case.
2314 __ andi(r0, result_, Operand(kIsNotStringMask)); 2303 __ mov(r0, Operand(kIsNotStringMask));
2315 __ bne(receiver_not_string_, cr0); 2304 __ AndP(r0, result_);
2305 __ bne(receiver_not_string_);
2316 } 2306 }
2317 2307
2318 // If the index is non-smi trigger the non-smi case. 2308 // If the index is non-smi trigger the non-smi case.
2319 __ JumpIfNotSmi(index_, &index_not_smi_); 2309 __ JumpIfNotSmi(index_, &index_not_smi_);
2320 __ bind(&got_smi_index_); 2310 __ bind(&got_smi_index_);
2321 2311
2322 // Check for index out of range. 2312 // Check for index out of range.
2323 __ LoadP(ip, FieldMemOperand(object_, String::kLengthOffset)); 2313 __ LoadP(ip, FieldMemOperand(object_, String::kLengthOffset));
2324 __ cmpl(ip, index_); 2314 __ CmpLogicalP(ip, index_);
2325 __ ble(index_out_of_range_); 2315 __ ble(index_out_of_range_);
2326 2316
2327 __ SmiUntag(index_); 2317 __ SmiUntag(index_);
2328 2318
2329 StringCharLoadGenerator::Generate(masm, object_, index_, result_, 2319 StringCharLoadGenerator::Generate(masm, object_, index_, result_,
2330 &call_runtime_); 2320 &call_runtime_);
2331 2321
2332 __ SmiTag(result_); 2322 __ SmiTag(result_);
2333 __ bind(&exit_); 2323 __ bind(&exit_);
2334 } 2324 }
2335 2325
2336
2337 void StringCharCodeAtGenerator::GenerateSlow( 2326 void StringCharCodeAtGenerator::GenerateSlow(
2338 MacroAssembler* masm, EmbedMode embed_mode, 2327 MacroAssembler* masm, EmbedMode embed_mode,
2339 const RuntimeCallHelper& call_helper) { 2328 const RuntimeCallHelper& call_helper) {
2340 __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase); 2329 __ Abort(kUnexpectedFallthroughToCharCodeAtSlowCase);
2341 2330
2342 // Index is not a smi. 2331 // Index is not a smi.
2343 __ bind(&index_not_smi_); 2332 __ bind(&index_not_smi_);
2344 // If index is a heap number, try converting it to an integer. 2333 // If index is a heap number, try converting it to an integer.
2345 __ CheckMap(index_, result_, Heap::kHeapNumberMapRootIndex, index_not_number_, 2334 __ CheckMap(index_, result_, Heap::kHeapNumberMapRootIndex, index_not_number_,
2346 DONT_DO_SMI_CHECK); 2335 DONT_DO_SMI_CHECK);
2347 call_helper.BeforeCall(masm); 2336 call_helper.BeforeCall(masm);
2348 if (embed_mode == PART_OF_IC_HANDLER) { 2337 if (embed_mode == PART_OF_IC_HANDLER) {
2349 __ Push(LoadWithVectorDescriptor::VectorRegister(), 2338 __ Push(LoadWithVectorDescriptor::VectorRegister(),
2350 LoadWithVectorDescriptor::SlotRegister(), object_, index_); 2339 LoadWithVectorDescriptor::SlotRegister(), object_, index_);
2351 } else { 2340 } else {
2352 // index_ is consumed by runtime conversion function. 2341 // index_ is consumed by runtime conversion function.
2353 __ Push(object_, index_); 2342 __ Push(object_, index_);
2354 } 2343 }
2355 if (index_flags_ == STRING_INDEX_IS_NUMBER) { 2344 if (index_flags_ == STRING_INDEX_IS_NUMBER) {
2356 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero); 2345 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
2357 } else { 2346 } else {
2358 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 2347 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
2359 // NumberToSmi discards numbers that are not exact integers. 2348 // NumberToSmi discards numbers that are not exact integers.
2360 __ CallRuntime(Runtime::kNumberToSmi); 2349 __ CallRuntime(Runtime::kNumberToSmi);
2361 } 2350 }
2362 // Save the conversion result before the pop instructions below 2351 // Save the conversion result before the pop instructions below
2363 // have a chance to overwrite it. 2352 // have a chance to overwrite it.
2364 __ Move(index_, r3); 2353 __ Move(index_, r2);
2365 if (embed_mode == PART_OF_IC_HANDLER) { 2354 if (embed_mode == PART_OF_IC_HANDLER) {
2366 __ Pop(LoadWithVectorDescriptor::VectorRegister(), 2355 __ Pop(LoadWithVectorDescriptor::VectorRegister(),
2367 LoadWithVectorDescriptor::SlotRegister(), object_); 2356 LoadWithVectorDescriptor::SlotRegister(), object_);
2368 } else { 2357 } else {
2369 __ pop(object_); 2358 __ pop(object_);
2370 } 2359 }
2371 // Reload the instance type. 2360 // Reload the instance type.
2372 __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 2361 __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
2373 __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 2362 __ LoadlB(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
2374 call_helper.AfterCall(masm); 2363 call_helper.AfterCall(masm);
2375 // If index is still not a smi, it must be out of range. 2364 // If index is still not a smi, it must be out of range.
2376 __ JumpIfNotSmi(index_, index_out_of_range_); 2365 __ JumpIfNotSmi(index_, index_out_of_range_);
2377 // Otherwise, return to the fast path. 2366 // Otherwise, return to the fast path.
2378 __ b(&got_smi_index_); 2367 __ b(&got_smi_index_);
2379 2368
2380 // Call runtime. We get here when the receiver is a string and the 2369 // Call runtime. We get here when the receiver is a string and the
2381 // index is a number, but the code of getting the actual character 2370 // index is a number, but the code of getting the actual character
2382 // is too complex (e.g., when the string needs to be flattened). 2371 // is too complex (e.g., when the string needs to be flattened).
2383 __ bind(&call_runtime_); 2372 __ bind(&call_runtime_);
2384 call_helper.BeforeCall(masm); 2373 call_helper.BeforeCall(masm);
2385 __ SmiTag(index_); 2374 __ SmiTag(index_);
2386 __ Push(object_, index_); 2375 __ Push(object_, index_);
2387 __ CallRuntime(Runtime::kStringCharCodeAtRT); 2376 __ CallRuntime(Runtime::kStringCharCodeAtRT);
2388 __ Move(result_, r3); 2377 __ Move(result_, r2);
2389 call_helper.AfterCall(masm); 2378 call_helper.AfterCall(masm);
2390 __ b(&exit_); 2379 __ b(&exit_);
2391 2380
2392 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 2381 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
2393 } 2382 }
2394 2383
2395
2396 // ------------------------------------------------------------------------- 2384 // -------------------------------------------------------------------------
2397 // StringCharFromCodeGenerator 2385 // StringCharFromCodeGenerator
2398 2386
2399 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 2387 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
2400 // Fast case of Heap::LookupSingleCharacterStringFromCode. 2388 // Fast case of Heap::LookupSingleCharacterStringFromCode.
2401 DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1)); 2389 DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1));
2402 __ LoadSmiLiteral(r0, Smi::FromInt(~String::kMaxOneByteCharCodeU)); 2390 __ LoadSmiLiteral(r0, Smi::FromInt(~String::kMaxOneByteCharCodeU));
2403 __ ori(r0, r0, Operand(kSmiTagMask)); 2391 __ OrP(r0, r0, Operand(kSmiTagMask));
2404 __ and_(r0, code_, r0, SetRC); 2392 __ AndP(r0, code_, r0);
2405 __ bne(&slow_case_, cr0); 2393 __ bne(&slow_case_);
2406 2394
2407 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 2395 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
2408 // At this point code register contains smi tagged one-byte char code. 2396 // At this point code register contains smi tagged one-byte char code.
2409 __ mr(r0, code_); 2397 __ LoadRR(r0, code_);
2410 __ SmiToPtrArrayOffset(code_, code_); 2398 __ SmiToPtrArrayOffset(code_, code_);
2411 __ add(result_, result_, code_); 2399 __ AddP(result_, code_);
2412 __ mr(code_, r0); 2400 __ LoadRR(code_, r0);
2413 __ LoadP(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); 2401 __ LoadP(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
2414 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex); 2402 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
2415 __ beq(&slow_case_); 2403 __ beq(&slow_case_);
2416 __ bind(&exit_); 2404 __ bind(&exit_);
2417 } 2405 }
2418 2406
2419
2420 void StringCharFromCodeGenerator::GenerateSlow( 2407 void StringCharFromCodeGenerator::GenerateSlow(
2421 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { 2408 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
2422 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 2409 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
2423 2410
2424 __ bind(&slow_case_); 2411 __ bind(&slow_case_);
2425 call_helper.BeforeCall(masm); 2412 call_helper.BeforeCall(masm);
2426 __ push(code_); 2413 __ push(code_);
2427 __ CallRuntime(Runtime::kStringCharFromCode); 2414 __ CallRuntime(Runtime::kStringCharFromCode);
2428 __ Move(result_, r3); 2415 __ Move(result_, r2);
2429 call_helper.AfterCall(masm); 2416 call_helper.AfterCall(masm);
2430 __ b(&exit_); 2417 __ b(&exit_);
2431 2418
2432 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 2419 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
2433 } 2420 }
2434 2421
2435 2422 enum CopyCharactersFlags { COPY_ASCII = 1, DEST_ALWAYS_ALIGNED = 2 };
2436 enum CopyCharactersFlags { COPY_ONE_BYTE = 1, DEST_ALWAYS_ALIGNED = 2 };
2437
2438 2423
2439 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, Register dest, 2424 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, Register dest,
2440 Register src, Register count, 2425 Register src, Register count,
2441 Register scratch, 2426 Register scratch,
2442 String::Encoding encoding) { 2427 String::Encoding encoding) {
2443 if (FLAG_debug_code) { 2428 if (FLAG_debug_code) {
2444 // Check that destination is word aligned. 2429 // Check that destination is word aligned.
2445 __ andi(r0, dest, Operand(kPointerAlignmentMask)); 2430 __ mov(r0, Operand(kPointerAlignmentMask));
2431 __ AndP(r0, dest);
2446 __ Check(eq, kDestinationOfCopyNotAligned, cr0); 2432 __ Check(eq, kDestinationOfCopyNotAligned, cr0);
2447 } 2433 }
2448 2434
2449 // Nothing to do for zero characters. 2435 // Nothing to do for zero characters.
2450 Label done; 2436 Label done;
2451 if (encoding == String::TWO_BYTE_ENCODING) { 2437 if (encoding == String::TWO_BYTE_ENCODING) {
2452 // double the length 2438 // double the length
2453 __ add(count, count, count, LeaveOE, SetRC); 2439 __ AddP(count, count, count);
2454 __ beq(&done, cr0); 2440 __ beq(&done, Label::kNear);
2455 } else { 2441 } else {
2456 __ cmpi(count, Operand::Zero()); 2442 __ CmpP(count, Operand::Zero());
2457 __ beq(&done); 2443 __ beq(&done, Label::kNear);
2458 } 2444 }
2459 2445
2460 // Copy count bytes from src to dst. 2446 // Copy count bytes from src to dst.
2461 Label byte_loop; 2447 Label byte_loop;
2462 __ mtctr(count); 2448 // TODO(joransiu): Convert into MVC loop
2463 __ bind(&byte_loop); 2449 __ bind(&byte_loop);
2464 __ lbz(scratch, MemOperand(src)); 2450 __ LoadlB(scratch, MemOperand(src));
2465 __ addi(src, src, Operand(1)); 2451 __ la(src, MemOperand(src, 1));
2466 __ stb(scratch, MemOperand(dest)); 2452 __ stc(scratch, MemOperand(dest));
2467 __ addi(dest, dest, Operand(1)); 2453 __ la(dest, MemOperand(dest, 1));
2468 __ bdnz(&byte_loop); 2454 __ BranchOnCount(count, &byte_loop);
2469 2455
2470 __ bind(&done); 2456 __ bind(&done);
2471 } 2457 }
2472 2458
2473
2474 void SubStringStub::Generate(MacroAssembler* masm) { 2459 void SubStringStub::Generate(MacroAssembler* masm) {
2475 Label runtime; 2460 Label runtime;
2476 2461
2477 // Stack frame on entry. 2462 // Stack frame on entry.
2478 // lr: return address 2463 // lr: return address
2479 // sp[0]: to 2464 // sp[0]: to
2480 // sp[4]: from 2465 // sp[4]: from
2481 // sp[8]: string 2466 // sp[8]: string
2482 2467
2483 // This stub is called from the native-call %_SubString(...), so 2468 // This stub is called from the native-call %_SubString(...), so
2484 // nothing can be assumed about the arguments. It is tested that: 2469 // nothing can be assumed about the arguments. It is tested that:
2485 // "string" is a sequential string, 2470 // "string" is a sequential string,
2486 // both "from" and "to" are smis, and 2471 // both "from" and "to" are smis, and
2487 // 0 <= from <= to <= string.length. 2472 // 0 <= from <= to <= string.length.
2488 // If any of these assumptions fail, we call the runtime system. 2473 // If any of these assumptions fail, we call the runtime system.
2489 2474
2490 const int kToOffset = 0 * kPointerSize; 2475 const int kToOffset = 0 * kPointerSize;
2491 const int kFromOffset = 1 * kPointerSize; 2476 const int kFromOffset = 1 * kPointerSize;
2492 const int kStringOffset = 2 * kPointerSize; 2477 const int kStringOffset = 2 * kPointerSize;
2493 2478
2494 __ LoadP(r5, MemOperand(sp, kToOffset)); 2479 __ LoadP(r4, MemOperand(sp, kToOffset));
2495 __ LoadP(r6, MemOperand(sp, kFromOffset)); 2480 __ LoadP(r5, MemOperand(sp, kFromOffset));
2496 2481
2497 // If either to or from had the smi tag bit set, then fail to generic runtime 2482 // If either to or from had the smi tag bit set, then fail to generic runtime
2483 __ JumpIfNotSmi(r4, &runtime);
2498 __ JumpIfNotSmi(r5, &runtime); 2484 __ JumpIfNotSmi(r5, &runtime);
2499 __ JumpIfNotSmi(r6, &runtime); 2485 __ SmiUntag(r4);
2500 __ SmiUntag(r5); 2486 __ SmiUntag(r5);
2501 __ SmiUntag(r6, SetRC); 2487 // Both r4 and r5 are untagged integers.
2502 // Both r5 and r6 are untagged integers.
2503 2488
2504 // We want to bailout to runtime here if From is negative. 2489 // We want to bailout to runtime here if From is negative.
2505 __ blt(&runtime, cr0); // From < 0. 2490 __ blt(&runtime); // From < 0.
2506 2491
2507 __ cmpl(r6, r5); 2492 __ CmpLogicalP(r5, r4);
2508 __ bgt(&runtime); // Fail if from > to. 2493 __ bgt(&runtime); // Fail if from > to.
2509 __ sub(r5, r5, r6); 2494 __ SubP(r4, r4, r5);
2510 2495
2511 // Make sure first argument is a string. 2496 // Make sure first argument is a string.
2512 __ LoadP(r3, MemOperand(sp, kStringOffset)); 2497 __ LoadP(r2, MemOperand(sp, kStringOffset));
2513 __ JumpIfSmi(r3, &runtime); 2498 __ JumpIfSmi(r2, &runtime);
2514 Condition is_string = masm->IsObjectStringType(r3, r4); 2499 Condition is_string = masm->IsObjectStringType(r2, r3);
2515 __ b(NegateCondition(is_string), &runtime, cr0); 2500 __ b(NegateCondition(is_string), &runtime);
2516 2501
2517 Label single_char; 2502 Label single_char;
2518 __ cmpi(r5, Operand(1)); 2503 __ CmpP(r4, Operand(1));
2519 __ b(eq, &single_char); 2504 __ b(eq, &single_char);
2520 2505
2521 // Short-cut for the case of trivial substring. 2506 // Short-cut for the case of trivial substring.
2522 Label return_r3; 2507 Label return_r2;
2523 // r3: original string 2508 // r2: original string
2524 // r5: result string length 2509 // r4: result string length
2525 __ LoadP(r7, FieldMemOperand(r3, String::kLengthOffset)); 2510 __ LoadP(r6, FieldMemOperand(r2, String::kLengthOffset));
2526 __ SmiUntag(r0, r7); 2511 __ SmiUntag(r0, r6);
2527 __ cmpl(r5, r0); 2512 __ CmpLogicalP(r4, r0);
2528 // Return original string. 2513 // Return original string.
2529 __ beq(&return_r3); 2514 __ beq(&return_r2);
2530 // Longer than original string's length or negative: unsafe arguments. 2515 // Longer than original string's length or negative: unsafe arguments.
2531 __ bgt(&runtime); 2516 __ bgt(&runtime);
2532 // Shorter than original string's length: an actual substring. 2517 // Shorter than original string's length: an actual substring.
2533 2518
2534 // Deal with different string types: update the index if necessary 2519 // Deal with different string types: update the index if necessary
2535 // and put the underlying string into r8. 2520 // and put the underlying string into r7.
2536 // r3: original string 2521 // r2: original string
2537 // r4: instance type 2522 // r3: instance type
2538 // r5: length 2523 // r4: length
2539 // r6: from index (untagged) 2524 // r5: from index (untagged)
2540 Label underlying_unpacked, sliced_string, seq_or_external_string; 2525 Label underlying_unpacked, sliced_string, seq_or_external_string;
2541 // If the string is not indirect, it can only be sequential or external. 2526 // If the string is not indirect, it can only be sequential or external.
2542 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 2527 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
2543 STATIC_ASSERT(kIsIndirectStringMask != 0); 2528 STATIC_ASSERT(kIsIndirectStringMask != 0);
2544 __ andi(r0, r4, Operand(kIsIndirectStringMask)); 2529 __ mov(r0, Operand(kIsIndirectStringMask));
2545 __ beq(&seq_or_external_string, cr0); 2530 __ AndP(r0, r3);
2531 __ beq(&seq_or_external_string);
2546 2532
2547 __ andi(r0, r4, Operand(kSlicedNotConsMask)); 2533 __ mov(r0, Operand(kSlicedNotConsMask));
2548 __ bne(&sliced_string, cr0); 2534 __ AndP(r0, r3);
2535 __ bne(&sliced_string);
2549 // Cons string. Check whether it is flat, then fetch first part. 2536 // Cons string. Check whether it is flat, then fetch first part.
2550 __ LoadP(r8, FieldMemOperand(r3, ConsString::kSecondOffset)); 2537 __ LoadP(r7, FieldMemOperand(r2, ConsString::kSecondOffset));
2551 __ CompareRoot(r8, Heap::kempty_stringRootIndex); 2538 __ CompareRoot(r7, Heap::kempty_stringRootIndex);
2552 __ bne(&runtime); 2539 __ bne(&runtime);
2553 __ LoadP(r8, FieldMemOperand(r3, ConsString::kFirstOffset)); 2540 __ LoadP(r7, FieldMemOperand(r2, ConsString::kFirstOffset));
2554 // Update instance type. 2541 // Update instance type.
2555 __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset)); 2542 __ LoadP(r3, FieldMemOperand(r7, HeapObject::kMapOffset));
2556 __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 2543 __ LoadlB(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
2557 __ b(&underlying_unpacked); 2544 __ b(&underlying_unpacked);
2558 2545
2559 __ bind(&sliced_string); 2546 __ bind(&sliced_string);
2560 // Sliced string. Fetch parent and correct start index by offset. 2547 // Sliced string. Fetch parent and correct start index by offset.
2561 __ LoadP(r8, FieldMemOperand(r3, SlicedString::kParentOffset)); 2548 __ LoadP(r7, FieldMemOperand(r2, SlicedString::kParentOffset));
2562 __ LoadP(r7, FieldMemOperand(r3, SlicedString::kOffsetOffset)); 2549 __ LoadP(r6, FieldMemOperand(r2, SlicedString::kOffsetOffset));
2563 __ SmiUntag(r4, r7); 2550 __ SmiUntag(r3, r6);
2564 __ add(r6, r6, r4); // Add offset to index. 2551 __ AddP(r5, r3); // Add offset to index.
2565 // Update instance type. 2552 // Update instance type.
2566 __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset)); 2553 __ LoadP(r3, FieldMemOperand(r7, HeapObject::kMapOffset));
2567 __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 2554 __ LoadlB(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
2568 __ b(&underlying_unpacked); 2555 __ b(&underlying_unpacked);
2569 2556
2570 __ bind(&seq_or_external_string); 2557 __ bind(&seq_or_external_string);
2571 // Sequential or external string. Just move string to the expected register. 2558 // Sequential or external string. Just move string to the expected register.
2572 __ mr(r8, r3); 2559 __ LoadRR(r7, r2);
2573 2560
2574 __ bind(&underlying_unpacked); 2561 __ bind(&underlying_unpacked);
2575 2562
2576 if (FLAG_string_slices) { 2563 if (FLAG_string_slices) {
2577 Label copy_routine; 2564 Label copy_routine;
2578 // r8: underlying subject string 2565 // r7: underlying subject string
2579 // r4: instance type of underlying subject string 2566 // r3: instance type of underlying subject string
2580 // r5: length 2567 // r4: length
2581 // r6: adjusted start index (untagged) 2568 // r5: adjusted start index (untagged)
2582 __ cmpi(r5, Operand(SlicedString::kMinLength)); 2569 __ CmpP(r4, Operand(SlicedString::kMinLength));
2583 // Short slice. Copy instead of slicing. 2570 // Short slice. Copy instead of slicing.
2584 __ blt(&copy_routine); 2571 __ blt(&copy_routine);
2585 // Allocate new sliced string. At this point we do not reload the instance 2572 // Allocate new sliced string. At this point we do not reload the instance
2586 // type including the string encoding because we simply rely on the info 2573 // type including the string encoding because we simply rely on the info
2587 // provided by the original string. It does not matter if the original 2574 // provided by the original string. It does not matter if the original
2588 // string's encoding is wrong because we always have to recheck encoding of 2575 // string's encoding is wrong because we always have to recheck encoding of
2589 // the newly created string's parent anyways due to externalized strings. 2576 // the newly created string's parent anyways due to externalized strings.
2590 Label two_byte_slice, set_slice_header; 2577 Label two_byte_slice, set_slice_header;
2591 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 2578 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
2592 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 2579 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
2593 __ andi(r0, r4, Operand(kStringEncodingMask)); 2580 __ mov(r0, Operand(kStringEncodingMask));
2594 __ beq(&two_byte_slice, cr0); 2581 __ AndP(r0, r3);
2595 __ AllocateOneByteSlicedString(r3, r5, r9, r10, &runtime); 2582 __ beq(&two_byte_slice);
2583 __ AllocateOneByteSlicedString(r2, r4, r8, r9, &runtime);
2596 __ b(&set_slice_header); 2584 __ b(&set_slice_header);
2597 __ bind(&two_byte_slice); 2585 __ bind(&two_byte_slice);
2598 __ AllocateTwoByteSlicedString(r3, r5, r9, r10, &runtime); 2586 __ AllocateTwoByteSlicedString(r2, r4, r8, r9, &runtime);
2599 __ bind(&set_slice_header); 2587 __ bind(&set_slice_header);
2600 __ SmiTag(r6); 2588 __ SmiTag(r5);
2601 __ StoreP(r8, FieldMemOperand(r3, SlicedString::kParentOffset), r0); 2589 __ StoreP(r7, FieldMemOperand(r2, SlicedString::kParentOffset));
2602 __ StoreP(r6, FieldMemOperand(r3, SlicedString::kOffsetOffset), r0); 2590 __ StoreP(r5, FieldMemOperand(r2, SlicedString::kOffsetOffset));
2603 __ b(&return_r3); 2591 __ b(&return_r2);
2604 2592
2605 __ bind(&copy_routine); 2593 __ bind(&copy_routine);
2606 } 2594 }
2607 2595
2608 // r8: underlying subject string 2596 // r7: underlying subject string
2609 // r4: instance type of underlying subject string 2597 // r3: instance type of underlying subject string
2610 // r5: length 2598 // r4: length
2611 // r6: adjusted start index (untagged) 2599 // r5: adjusted start index (untagged)
2612 Label two_byte_sequential, sequential_string, allocate_result; 2600 Label two_byte_sequential, sequential_string, allocate_result;
2613 STATIC_ASSERT(kExternalStringTag != 0); 2601 STATIC_ASSERT(kExternalStringTag != 0);
2614 STATIC_ASSERT(kSeqStringTag == 0); 2602 STATIC_ASSERT(kSeqStringTag == 0);
2615 __ andi(r0, r4, Operand(kExternalStringTag)); 2603 __ mov(r0, Operand(kExternalStringTag));
2616 __ beq(&sequential_string, cr0); 2604 __ AndP(r0, r3);
2605 __ beq(&sequential_string);
2617 2606
2618 // Handle external string. 2607 // Handle external string.
2619 // Rule out short external strings. 2608 // Rule out short external strings.
2620 STATIC_ASSERT(kShortExternalStringTag != 0); 2609 STATIC_ASSERT(kShortExternalStringTag != 0);
2621 __ andi(r0, r4, Operand(kShortExternalStringTag)); 2610 __ mov(r0, Operand(kShortExternalStringTag));
2622 __ bne(&runtime, cr0); 2611 __ AndP(r0, r3);
2623 __ LoadP(r8, FieldMemOperand(r8, ExternalString::kResourceDataOffset)); 2612 __ bne(&runtime);
2624 // r8 already points to the first character of underlying string. 2613 __ LoadP(r7, FieldMemOperand(r7, ExternalString::kResourceDataOffset));
2614 // r7 already points to the first character of underlying string.
2625 __ b(&allocate_result); 2615 __ b(&allocate_result);
2626 2616
2627 __ bind(&sequential_string); 2617 __ bind(&sequential_string);
2628 // Locate first character of underlying subject string. 2618 // Locate first character of underlying subject string.
2629 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 2619 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2630 __ addi(r8, r8, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 2620 __ AddP(r7, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
2631 2621
2632 __ bind(&allocate_result); 2622 __ bind(&allocate_result);
2633 // Sequential acii string. Allocate the result. 2623 // Sequential acii string. Allocate the result.
2634 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 2624 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
2635 __ andi(r0, r4, Operand(kStringEncodingMask)); 2625 __ mov(r0, Operand(kStringEncodingMask));
2636 __ beq(&two_byte_sequential, cr0); 2626 __ AndP(r0, r3);
2627 __ beq(&two_byte_sequential);
2637 2628
2638 // Allocate and copy the resulting one-byte string. 2629 // Allocate and copy the resulting one-byte string.
2639 __ AllocateOneByteString(r3, r5, r7, r9, r10, &runtime); 2630 __ AllocateOneByteString(r2, r4, r6, r8, r9, &runtime);
2640 2631
2641 // Locate first character of substring to copy. 2632 // Locate first character of substring to copy.
2642 __ add(r8, r8, r6); 2633 __ AddP(r7, r5);
2643 // Locate first character of result. 2634 // Locate first character of result.
2644 __ addi(r4, r3, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 2635 __ AddP(r3, r2, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
2645 2636
2646 // r3: result string 2637 // r2: result string
2647 // r4: first character of result string 2638 // r3: first character of result string
2648 // r5: result string length 2639 // r4: result string length
2649 // r8: first character of substring to copy 2640 // r7: first character of substring to copy
2650 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 2641 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
2651 StringHelper::GenerateCopyCharacters(masm, r4, r8, r5, r6, 2642 StringHelper::GenerateCopyCharacters(masm, r3, r7, r4, r5,
2652 String::ONE_BYTE_ENCODING); 2643 String::ONE_BYTE_ENCODING);
2653 __ b(&return_r3); 2644 __ b(&return_r2);
2654 2645
2655 // Allocate and copy the resulting two-byte string. 2646 // Allocate and copy the resulting two-byte string.
2656 __ bind(&two_byte_sequential); 2647 __ bind(&two_byte_sequential);
2657 __ AllocateTwoByteString(r3, r5, r7, r9, r10, &runtime); 2648 __ AllocateTwoByteString(r2, r4, r6, r8, r9, &runtime);
2658 2649
2659 // Locate first character of substring to copy. 2650 // Locate first character of substring to copy.
2660 __ ShiftLeftImm(r4, r6, Operand(1)); 2651 __ ShiftLeftP(r3, r5, Operand(1));
2661 __ add(r8, r8, r4); 2652 __ AddP(r7, r3);
2662 // Locate first character of result. 2653 // Locate first character of result.
2663 __ addi(r4, r3, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 2654 __ AddP(r3, r2, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2664 2655
2665 // r3: result string. 2656 // r2: result string.
2666 // r4: first character of result. 2657 // r3: first character of result.
2667 // r5: result length. 2658 // r4: result length.
2668 // r8: first character of substring to copy. 2659 // r7: first character of substring to copy.
2669 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 2660 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
2670 StringHelper::GenerateCopyCharacters(masm, r4, r8, r5, r6, 2661 StringHelper::GenerateCopyCharacters(masm, r3, r7, r4, r5,
2671 String::TWO_BYTE_ENCODING); 2662 String::TWO_BYTE_ENCODING);
2672 2663
2673 __ bind(&return_r3); 2664 __ bind(&return_r2);
2674 Counters* counters = isolate()->counters(); 2665 Counters* counters = isolate()->counters();
2675 __ IncrementCounter(counters->sub_string_native(), 1, r6, r7); 2666 __ IncrementCounter(counters->sub_string_native(), 1, r5, r6);
2676 __ Drop(3); 2667 __ Drop(3);
2677 __ Ret(); 2668 __ Ret();
2678 2669
2679 // Just jump to runtime to create the sub string. 2670 // Just jump to runtime to create the sub string.
2680 __ bind(&runtime); 2671 __ bind(&runtime);
2681 __ TailCallRuntime(Runtime::kSubString); 2672 __ TailCallRuntime(Runtime::kSubString);
2682 2673
2683 __ bind(&single_char); 2674 __ bind(&single_char);
2684 // r3: original string 2675 // r2: original string
2685 // r4: instance type 2676 // r3: instance type
2686 // r5: length 2677 // r4: length
2687 // r6: from index (untagged) 2678 // r5: from index (untagged)
2688 __ SmiTag(r6, r6); 2679 __ SmiTag(r5, r5);
2689 StringCharAtGenerator generator(r3, r6, r5, r3, &runtime, &runtime, &runtime, 2680 StringCharAtGenerator generator(r2, r5, r4, r2, &runtime, &runtime, &runtime,
2690 STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING); 2681 STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
2691 generator.GenerateFast(masm); 2682 generator.GenerateFast(masm);
2692 __ Drop(3); 2683 __ Drop(3);
2693 __ Ret(); 2684 __ Ret();
2694 generator.SkipSlow(masm, &runtime); 2685 generator.SkipSlow(masm, &runtime);
2695 } 2686 }
2696 2687
2697
2698 void ToNumberStub::Generate(MacroAssembler* masm) { 2688 void ToNumberStub::Generate(MacroAssembler* masm) {
2699 // The ToNumber stub takes one argument in r3. 2689 // The ToNumber stub takes one argument in r2.
2700 Label not_smi; 2690 Label not_smi;
2701 __ JumpIfNotSmi(r3, &not_smi); 2691 __ JumpIfNotSmi(r2, &not_smi);
2702 __ blr(); 2692 __ b(r14);
2703 __ bind(&not_smi); 2693 __ bind(&not_smi);
2704 2694
2705 __ CompareObjectType(r3, r4, r4, HEAP_NUMBER_TYPE); 2695 __ CompareObjectType(r2, r3, r3, HEAP_NUMBER_TYPE);
2706 // r3: receiver 2696 // r2: receiver
2707 // r4: receiver instance type 2697 // r3: receiver instance type
2708 __ Ret(eq); 2698 Label not_heap_number;
2699 __ bne(&not_heap_number);
2700 __ Ret();
2701 __ bind(&not_heap_number);
2709 2702
2710 Label not_string, slow_string; 2703 Label not_string, slow_string;
2711 __ cmpli(r4, Operand(FIRST_NONSTRING_TYPE)); 2704 __ CmpLogicalP(r3, Operand(FIRST_NONSTRING_TYPE));
2712 __ bge(&not_string); 2705 __ bge(&not_string, Label::kNear);
2713 // Check if string has a cached array index. 2706 // Check if string has a cached array index.
2714 __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset)); 2707 __ LoadlW(r4, FieldMemOperand(r2, String::kHashFieldOffset));
2715 __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC); 2708 __ AndP(r0, r4, Operand(String::kContainsCachedArrayIndexMask));
2716 __ bne(&slow_string, cr0); 2709 __ bne(&slow_string, Label::kNear);
2717 __ IndexFromHash(r5, r3); 2710 __ IndexFromHash(r4, r2);
2718 __ blr(); 2711 __ b(r14);
2719 __ bind(&slow_string); 2712 __ bind(&slow_string);
2720 __ push(r3); // Push argument. 2713 __ push(r2); // Push argument.
2721 __ TailCallRuntime(Runtime::kStringToNumber); 2714 __ TailCallRuntime(Runtime::kStringToNumber);
2722 __ bind(&not_string); 2715 __ bind(&not_string);
2723 2716
2724 Label not_oddball; 2717 Label not_oddball;
2725 __ cmpi(r4, Operand(ODDBALL_TYPE)); 2718 __ CmpP(r3, Operand(ODDBALL_TYPE));
2726 __ bne(&not_oddball); 2719 __ bne(&not_oddball, Label::kNear);
2727 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); 2720 __ LoadP(r2, FieldMemOperand(r2, Oddball::kToNumberOffset));
2728 __ blr(); 2721 __ b(r14);
2729 __ bind(&not_oddball); 2722 __ bind(&not_oddball);
2730 2723
2731 __ push(r3); // Push argument. 2724 __ push(r2); // Push argument.
2732 __ TailCallRuntime(Runtime::kToNumber); 2725 __ TailCallRuntime(Runtime::kToNumber);
2733 } 2726 }
2734 2727
2735
2736 void ToLengthStub::Generate(MacroAssembler* masm) { 2728 void ToLengthStub::Generate(MacroAssembler* masm) {
2737 // The ToLength stub takes one argument in r3. 2729 // The ToLength stub takes one argument in r2.
2738 Label not_smi; 2730 Label not_smi;
2739 __ JumpIfNotSmi(r3, &not_smi); 2731 __ JumpIfNotSmi(r2, &not_smi);
2740 STATIC_ASSERT(kSmiTag == 0); 2732 STATIC_ASSERT(kSmiTag == 0);
2741 __ cmpi(r3, Operand::Zero()); 2733 __ CmpP(r2, Operand::Zero());
2742 if (CpuFeatures::IsSupported(ISELECT)) { 2734 Label positive;
2743 __ isel(lt, r3, r0, r3); 2735 __ bgt(&positive);
2744 } else { 2736 __ LoadImmP(r2, Operand::Zero());
2745 Label positive; 2737 __ bind(&positive);
2746 __ bgt(&positive);
2747 __ li(r3, Operand::Zero());
2748 __ bind(&positive);
2749 }
2750 __ Ret(); 2738 __ Ret();
2751 __ bind(&not_smi); 2739 __ bind(&not_smi);
2752 2740
2753 __ push(r3); // Push argument. 2741 __ push(r2); // Push argument.
2754 __ TailCallRuntime(Runtime::kToLength); 2742 __ TailCallRuntime(Runtime::kToLength);
2755 } 2743 }
2756 2744
2745 void ToStringStub::Generate(MacroAssembler* masm) {
2746 // The ToString stub takes one argument in r2.
2747 Label done;
2748 Label is_number;
2749 __ JumpIfSmi(r2, &is_number);
2757 2750
2758 void ToStringStub::Generate(MacroAssembler* masm) { 2751 __ CompareObjectType(r2, r3, r3, FIRST_NONSTRING_TYPE);
2759 // The ToString stub takes one argument in r3. 2752 // r2: receiver
2760 Label is_number; 2753 // r3: receiver instance type
2761 __ JumpIfSmi(r3, &is_number); 2754 __ blt(&done);
2762
2763 __ CompareObjectType(r3, r4, r4, FIRST_NONSTRING_TYPE);
2764 // r3: receiver
2765 // r4: receiver instance type
2766 __ Ret(lt);
2767 2755
2768 Label not_heap_number; 2756 Label not_heap_number;
2769 __ cmpi(r4, Operand(HEAP_NUMBER_TYPE)); 2757 __ CmpP(r3, Operand(HEAP_NUMBER_TYPE));
2770 __ bne(&not_heap_number); 2758 __ bne(&not_heap_number);
2771 __ bind(&is_number); 2759 __ bind(&is_number);
2772 NumberToStringStub stub(isolate()); 2760 NumberToStringStub stub(isolate());
2773 __ TailCallStub(&stub); 2761 __ TailCallStub(&stub);
2774 __ bind(&not_heap_number); 2762 __ bind(&not_heap_number);
2775 2763
2776 Label not_oddball; 2764 Label not_oddball;
2777 __ cmpi(r4, Operand(ODDBALL_TYPE)); 2765 __ CmpP(r3, Operand(ODDBALL_TYPE));
2778 __ bne(&not_oddball); 2766 __ bne(&not_oddball);
2779 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToStringOffset)); 2767 __ LoadP(r2, FieldMemOperand(r2, Oddball::kToStringOffset));
2780 __ Ret(); 2768 __ Ret();
2781 __ bind(&not_oddball); 2769 __ bind(&not_oddball);
2782 2770
2783 __ push(r3); // Push argument. 2771 __ push(r2); // Push argument.
2784 __ TailCallRuntime(Runtime::kToString); 2772 __ TailCallRuntime(Runtime::kToString);
2773
2774 __ bind(&done);
2775 __ Ret();
2785 } 2776 }
2786 2777
2787
2788 void ToNameStub::Generate(MacroAssembler* masm) { 2778 void ToNameStub::Generate(MacroAssembler* masm) {
2789 // The ToName stub takes one argument in r3. 2779 // The ToName stub takes one argument in r2.
2790 Label is_number; 2780 Label is_number;
2791 __ JumpIfSmi(r3, &is_number); 2781 __ JumpIfSmi(r2, &is_number);
2792 2782
2793 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); 2783 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
2794 __ CompareObjectType(r3, r4, r4, LAST_NAME_TYPE); 2784 __ CompareObjectType(r2, r3, r3, LAST_NAME_TYPE);
2795 // r3: receiver 2785 // r2: receiver
2796 // r4: receiver instance type 2786 // r3: receiver instance type
2797 __ Ret(le); 2787 __ Ret(le);
2798 2788
2799 Label not_heap_number; 2789 Label not_heap_number;
2800 __ cmpi(r4, Operand(HEAP_NUMBER_TYPE)); 2790 __ CmpP(r3, Operand(HEAP_NUMBER_TYPE));
2801 __ bne(&not_heap_number); 2791 __ bne(&not_heap_number);
2802 __ bind(&is_number); 2792 __ bind(&is_number);
2803 NumberToStringStub stub(isolate()); 2793 NumberToStringStub stub(isolate());
2804 __ TailCallStub(&stub); 2794 __ TailCallStub(&stub);
2805 __ bind(&not_heap_number); 2795 __ bind(&not_heap_number);
2806 2796
2807 Label not_oddball; 2797 Label not_oddball;
2808 __ cmpi(r4, Operand(ODDBALL_TYPE)); 2798 __ CmpP(r3, Operand(ODDBALL_TYPE));
2809 __ bne(&not_oddball); 2799 __ bne(&not_oddball);
2810 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToStringOffset)); 2800 __ LoadP(r2, FieldMemOperand(r2, Oddball::kToStringOffset));
2811 __ Ret(); 2801 __ Ret();
2812 __ bind(&not_oddball); 2802 __ bind(&not_oddball);
2813 2803
2814 __ push(r3); // Push argument. 2804 __ push(r2); // Push argument.
2815 __ TailCallRuntime(Runtime::kToName); 2805 __ TailCallRuntime(Runtime::kToName);
2816 } 2806 }
2817 2807
2818
2819 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, 2808 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
2820 Register left, 2809 Register left,
2821 Register right, 2810 Register right,
2822 Register scratch1, 2811 Register scratch1,
2823 Register scratch2) { 2812 Register scratch2) {
2824 Register length = scratch1; 2813 Register length = scratch1;
2825 2814
2826 // Compare lengths. 2815 // Compare lengths.
2827 Label strings_not_equal, check_zero_length; 2816 Label strings_not_equal, check_zero_length;
2828 __ LoadP(length, FieldMemOperand(left, String::kLengthOffset)); 2817 __ LoadP(length, FieldMemOperand(left, String::kLengthOffset));
2829 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); 2818 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
2830 __ cmp(length, scratch2); 2819 __ CmpP(length, scratch2);
2831 __ beq(&check_zero_length); 2820 __ beq(&check_zero_length);
2832 __ bind(&strings_not_equal); 2821 __ bind(&strings_not_equal);
2833 __ LoadSmiLiteral(r3, Smi::FromInt(NOT_EQUAL)); 2822 __ LoadSmiLiteral(r2, Smi::FromInt(NOT_EQUAL));
2834 __ Ret(); 2823 __ Ret();
2835 2824
2836 // Check if the length is zero. 2825 // Check if the length is zero.
2837 Label compare_chars; 2826 Label compare_chars;
2838 __ bind(&check_zero_length); 2827 __ bind(&check_zero_length);
2839 STATIC_ASSERT(kSmiTag == 0); 2828 STATIC_ASSERT(kSmiTag == 0);
2840 __ cmpi(length, Operand::Zero()); 2829 __ CmpP(length, Operand::Zero());
2841 __ bne(&compare_chars); 2830 __ bne(&compare_chars);
2842 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2831 __ LoadSmiLiteral(r2, Smi::FromInt(EQUAL));
2843 __ Ret(); 2832 __ Ret();
2844 2833
2845 // Compare characters. 2834 // Compare characters.
2846 __ bind(&compare_chars); 2835 __ bind(&compare_chars);
2847 GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2, 2836 GenerateOneByteCharsCompareLoop(masm, left, right, length, scratch2,
2848 &strings_not_equal); 2837 &strings_not_equal);
2849 2838
2850 // Characters are equal. 2839 // Characters are equal.
2851 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2840 __ LoadSmiLiteral(r2, Smi::FromInt(EQUAL));
2852 __ Ret(); 2841 __ Ret();
2853 } 2842 }
2854 2843
2855
2856 void StringHelper::GenerateCompareFlatOneByteStrings( 2844 void StringHelper::GenerateCompareFlatOneByteStrings(
2857 MacroAssembler* masm, Register left, Register right, Register scratch1, 2845 MacroAssembler* masm, Register left, Register right, Register scratch1,
2858 Register scratch2, Register scratch3) { 2846 Register scratch2, Register scratch3) {
2859 Label result_not_equal, compare_lengths; 2847 Label skip, result_not_equal, compare_lengths;
2860 // Find minimum length and length difference. 2848 // Find minimum length and length difference.
2861 __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset)); 2849 __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset));
2862 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset)); 2850 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
2863 __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC); 2851 __ SubP(scratch3, scratch1, scratch2 /*, LeaveOE, SetRC*/);
2852 // Removing RC looks okay here.
2864 Register length_delta = scratch3; 2853 Register length_delta = scratch3;
2865 if (CpuFeatures::IsSupported(ISELECT)) { 2854 __ ble(&skip, Label::kNear);
2866 __ isel(gt, scratch1, scratch2, scratch1, cr0); 2855 __ LoadRR(scratch1, scratch2);
2867 } else { 2856 __ bind(&skip);
2868 Label skip;
2869 __ ble(&skip, cr0);
2870 __ mr(scratch1, scratch2);
2871 __ bind(&skip);
2872 }
2873 Register min_length = scratch1; 2857 Register min_length = scratch1;
2874 STATIC_ASSERT(kSmiTag == 0); 2858 STATIC_ASSERT(kSmiTag == 0);
2875 __ cmpi(min_length, Operand::Zero()); 2859 __ CmpP(min_length, Operand::Zero());
2876 __ beq(&compare_lengths); 2860 __ beq(&compare_lengths);
2877 2861
2878 // Compare loop. 2862 // Compare loop.
2879 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2, 2863 GenerateOneByteCharsCompareLoop(masm, left, right, min_length, scratch2,
2880 &result_not_equal); 2864 &result_not_equal);
2881 2865
2882 // Compare lengths - strings up to min-length are equal. 2866 // Compare lengths - strings up to min-length are equal.
2883 __ bind(&compare_lengths); 2867 __ bind(&compare_lengths);
2884 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 2868 DCHECK(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
2885 // Use length_delta as result if it's zero. 2869 // Use length_delta as result if it's zero.
2886 __ mr(r3, length_delta); 2870 __ LoadRR(r2, length_delta);
2887 __ cmpi(r3, Operand::Zero()); 2871 __ CmpP(length_delta, Operand::Zero());
2888 __ bind(&result_not_equal); 2872 __ bind(&result_not_equal);
2889 // Conditionally update the result based either on length_delta or 2873 // Conditionally update the result based either on length_delta or
2890 // the last comparion performed in the loop above. 2874 // the last comparion performed in the loop above.
2891 if (CpuFeatures::IsSupported(ISELECT)) { 2875 Label less_equal, equal;
2892 __ LoadSmiLiteral(r4, Smi::FromInt(GREATER)); 2876 __ ble(&less_equal);
2893 __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); 2877 __ LoadSmiLiteral(r2, Smi::FromInt(GREATER));
2894 __ isel(eq, r3, r0, r4); 2878 __ Ret();
2895 __ isel(lt, r3, r5, r3); 2879 __ bind(&less_equal);
2896 __ Ret(); 2880 __ beq(&equal);
2897 } else { 2881 __ LoadSmiLiteral(r2, Smi::FromInt(LESS));
2898 Label less_equal, equal; 2882 __ bind(&equal);
2899 __ ble(&less_equal); 2883 __ Ret();
2900 __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
2901 __ Ret();
2902 __ bind(&less_equal);
2903 __ beq(&equal);
2904 __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
2905 __ bind(&equal);
2906 __ Ret();
2907 }
2908 } 2884 }
2909 2885
2910
2911 void StringHelper::GenerateOneByteCharsCompareLoop( 2886 void StringHelper::GenerateOneByteCharsCompareLoop(
2912 MacroAssembler* masm, Register left, Register right, Register length, 2887 MacroAssembler* masm, Register left, Register right, Register length,
2913 Register scratch1, Label* chars_not_equal) { 2888 Register scratch1, Label* chars_not_equal) {
2914 // Change index to run from -length to -1 by adding length to string 2889 // Change index to run from -length to -1 by adding length to string
2915 // start. This means that loop ends when index reaches zero, which 2890 // start. This means that loop ends when index reaches zero, which
2916 // doesn't need an additional compare. 2891 // doesn't need an additional compare.
2917 __ SmiUntag(length); 2892 __ SmiUntag(length);
2918 __ addi(scratch1, length, 2893 __ AddP(scratch1, length,
2919 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 2894 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
2920 __ add(left, left, scratch1); 2895 __ AddP(left, scratch1);
2921 __ add(right, right, scratch1); 2896 __ AddP(right, scratch1);
2922 __ subfic(length, length, Operand::Zero()); 2897 __ LoadComplementRR(length, length);
2923 Register index = length; // index = -length; 2898 Register index = length; // index = -length;
2924 2899
2925 // Compare loop. 2900 // Compare loop.
2926 Label loop; 2901 Label loop;
2927 __ bind(&loop); 2902 __ bind(&loop);
2928 __ lbzx(scratch1, MemOperand(left, index)); 2903 __ LoadlB(scratch1, MemOperand(left, index));
2929 __ lbzx(r0, MemOperand(right, index)); 2904 __ LoadlB(r0, MemOperand(right, index));
2930 __ cmp(scratch1, r0); 2905 __ CmpP(scratch1, r0);
2931 __ bne(chars_not_equal); 2906 __ bne(chars_not_equal);
2932 __ addi(index, index, Operand(1)); 2907 __ AddP(index, Operand(1));
2933 __ cmpi(index, Operand::Zero()); 2908 __ CmpP(index, Operand::Zero());
2934 __ bne(&loop); 2909 __ bne(&loop);
2935 } 2910 }
2936 2911
2937
2938 void StringCompareStub::Generate(MacroAssembler* masm) { 2912 void StringCompareStub::Generate(MacroAssembler* masm) {
2939 // ----------- S t a t e ------------- 2913 // ----------- S t a t e -------------
2940 // -- r4 : left 2914 // -- r3 : left
2941 // -- r3 : right 2915 // -- r2 : right
2942 // -- lr : return address 2916 // -- r14 : return address
2943 // ----------------------------------- 2917 // -----------------------------------
2944 __ AssertString(r4);
2945 __ AssertString(r3); 2918 __ AssertString(r3);
2919 __ AssertString(r2);
2946 2920
2947 Label not_same; 2921 Label not_same;
2948 __ cmp(r3, r4); 2922 __ CmpP(r2, r3);
2949 __ bne(&not_same); 2923 __ bne(&not_same);
2950 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 2924 __ LoadSmiLiteral(r2, Smi::FromInt(EQUAL));
2951 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r4, 2925 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r3,
2952 r5); 2926 r4);
2953 __ Ret(); 2927 __ Ret();
2954 2928
2955 __ bind(&not_same); 2929 __ bind(&not_same);
2956 2930
2957 // Check that both objects are sequential one-byte strings. 2931 // Check that both objects are sequential one-byte strings.
2958 Label runtime; 2932 Label runtime;
2959 __ JumpIfNotBothSequentialOneByteStrings(r4, r3, r5, r6, &runtime); 2933 __ JumpIfNotBothSequentialOneByteStrings(r3, r2, r4, r5, &runtime);
2960 2934
2961 // Compare flat one-byte strings natively. 2935 // Compare flat one-byte strings natively.
2962 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r5, 2936 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r4,
2963 r6); 2937 r5);
2964 StringHelper::GenerateCompareFlatOneByteStrings(masm, r4, r3, r5, r6, r7); 2938 StringHelper::GenerateCompareFlatOneByteStrings(masm, r3, r2, r4, r5, r6);
2965 2939
2966 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 2940 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
2967 // tagged as a small integer. 2941 // tagged as a small integer.
2968 __ bind(&runtime); 2942 __ bind(&runtime);
2969 __ Push(r4, r3); 2943 __ Push(r3, r2);
2970 __ TailCallRuntime(Runtime::kStringCompare); 2944 __ TailCallRuntime(Runtime::kStringCompare);
2971 } 2945 }
2972 2946
2973
2974 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 2947 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
2975 // ----------- S t a t e ------------- 2948 // ----------- S t a t e -------------
2976 // -- r4 : left 2949 // -- r3 : left
2977 // -- r3 : right 2950 // -- r2 : right
2978 // -- lr : return address 2951 // r3: second string
2979 // ----------------------------------- 2952 // -----------------------------------
2980 2953
2981 // Load r5 with the allocation site. We stick an undefined dummy value here 2954 // Load r4 with the allocation site. We stick an undefined dummy value here
2982 // and replace it with the real allocation site later when we instantiate this 2955 // and replace it with the real allocation site later when we instantiate this
2983 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 2956 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
2984 __ Move(r5, handle(isolate()->heap()->undefined_value())); 2957 __ Move(r4, handle(isolate()->heap()->undefined_value()));
2985 2958
2986 // Make sure that we actually patched the allocation site. 2959 // Make sure that we actually patched the allocation site.
2987 if (FLAG_debug_code) { 2960 if (FLAG_debug_code) {
2988 __ TestIfSmi(r5, r0); 2961 __ TestIfSmi(r4);
2989 __ Assert(ne, kExpectedAllocationSite, cr0); 2962 __ Assert(ne, kExpectedAllocationSite, cr0);
2990 __ push(r5); 2963 __ push(r4);
2991 __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset)); 2964 __ LoadP(r4, FieldMemOperand(r4, HeapObject::kMapOffset));
2992 __ LoadRoot(ip, Heap::kAllocationSiteMapRootIndex); 2965 __ CompareRoot(r4, Heap::kAllocationSiteMapRootIndex);
2993 __ cmp(r5, ip); 2966 __ pop(r4);
2994 __ pop(r5);
2995 __ Assert(eq, kExpectedAllocationSite); 2967 __ Assert(eq, kExpectedAllocationSite);
2996 } 2968 }
2997 2969
2998 // Tail call into the stub that handles binary operations with allocation 2970 // Tail call into the stub that handles binary operations with allocation
2999 // sites. 2971 // sites.
3000 BinaryOpWithAllocationSiteStub stub(isolate(), state()); 2972 BinaryOpWithAllocationSiteStub stub(isolate(), state());
3001 __ TailCallStub(&stub); 2973 __ TailCallStub(&stub);
3002 } 2974 }
3003 2975
3004
3005 void CompareICStub::GenerateBooleans(MacroAssembler* masm) { 2976 void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
3006 DCHECK_EQ(CompareICState::BOOLEAN, state()); 2977 DCHECK_EQ(CompareICState::BOOLEAN, state());
3007 Label miss; 2978 Label miss;
3008 2979
3009 __ CheckMap(r4, r5, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); 2980 __ CheckMap(r3, r4, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
3010 __ CheckMap(r3, r6, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK); 2981 __ CheckMap(r2, r5, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
3011 if (!Token::IsEqualityOp(op())) { 2982 if (!Token::IsEqualityOp(op())) {
3012 __ LoadP(r4, FieldMemOperand(r4, Oddball::kToNumberOffset));
3013 __ AssertSmi(r4);
3014 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset)); 2983 __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset));
3015 __ AssertSmi(r3); 2984 __ AssertSmi(r3);
2985 __ LoadP(r2, FieldMemOperand(r2, Oddball::kToNumberOffset));
2986 __ AssertSmi(r2);
3016 } 2987 }
3017 __ sub(r3, r4, r3); 2988 __ SubP(r2, r3, r2);
3018 __ Ret(); 2989 __ Ret();
3019 2990
3020 __ bind(&miss); 2991 __ bind(&miss);
3021 GenerateMiss(masm); 2992 GenerateMiss(masm);
3022 } 2993 }
3023 2994
3024
3025 void CompareICStub::GenerateSmis(MacroAssembler* masm) { 2995 void CompareICStub::GenerateSmis(MacroAssembler* masm) {
3026 DCHECK(state() == CompareICState::SMI); 2996 DCHECK(state() == CompareICState::SMI);
3027 Label miss; 2997 Label miss;
3028 __ orx(r5, r4, r3); 2998 __ OrP(r4, r3, r2);
3029 __ JumpIfNotSmi(r5, &miss); 2999 __ JumpIfNotSmi(r4, &miss);
3030 3000
3031 if (GetCondition() == eq) { 3001 if (GetCondition() == eq) {
3032 // For equality we do not care about the sign of the result. 3002 // For equality we do not care about the sign of the result.
3033 // __ sub(r3, r3, r4, SetCC); 3003 // __ sub(r2, r2, r3, SetCC);
3034 __ sub(r3, r3, r4); 3004 __ SubP(r2, r2, r3);
3035 } else { 3005 } else {
3036 // Untag before subtracting to avoid handling overflow. 3006 // Untag before subtracting to avoid handling overflow.
3037 __ SmiUntag(r4);
3038 __ SmiUntag(r3); 3007 __ SmiUntag(r3);
3039 __ sub(r3, r4, r3); 3008 __ SmiUntag(r2);
3009 __ SubP(r2, r3, r2);
3040 } 3010 }
3041 __ Ret(); 3011 __ Ret();
3042 3012
3043 __ bind(&miss); 3013 __ bind(&miss);
3044 GenerateMiss(masm); 3014 GenerateMiss(masm);
3045 } 3015 }
3046 3016
3047
3048 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { 3017 void CompareICStub::GenerateNumbers(MacroAssembler* masm) {
3049 DCHECK(state() == CompareICState::NUMBER); 3018 DCHECK(state() == CompareICState::NUMBER);
3050 3019
3051 Label generic_stub; 3020 Label generic_stub;
3052 Label unordered, maybe_undefined1, maybe_undefined2; 3021 Label unordered, maybe_undefined1, maybe_undefined2;
3053 Label miss; 3022 Label miss;
3054 Label equal, less_than; 3023 Label equal, less_than;
3055 3024
3056 if (left() == CompareICState::SMI) { 3025 if (left() == CompareICState::SMI) {
3057 __ JumpIfNotSmi(r4, &miss); 3026 __ JumpIfNotSmi(r3, &miss);
3058 } 3027 }
3059 if (right() == CompareICState::SMI) { 3028 if (right() == CompareICState::SMI) {
3060 __ JumpIfNotSmi(r3, &miss); 3029 __ JumpIfNotSmi(r2, &miss);
3061 } 3030 }
3062 3031
3063 // Inlining the double comparison and falling back to the general compare 3032 // Inlining the double comparison and falling back to the general compare
3064 // stub if NaN is involved. 3033 // stub if NaN is involved.
3065 // Load left and right operand. 3034 // Load left and right operand.
3066 Label done, left, left_smi, right_smi; 3035 Label done, left, left_smi, right_smi;
3067 __ JumpIfSmi(r3, &right_smi); 3036 __ JumpIfSmi(r2, &right_smi);
3068 __ CheckMap(r3, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, 3037 __ CheckMap(r2, r4, Heap::kHeapNumberMapRootIndex, &maybe_undefined1,
3069 DONT_DO_SMI_CHECK); 3038 DONT_DO_SMI_CHECK);
3070 __ lfd(d1, FieldMemOperand(r3, HeapNumber::kValueOffset)); 3039 __ LoadDouble(d1, FieldMemOperand(r2, HeapNumber::kValueOffset));
3071 __ b(&left); 3040 __ b(&left);
3072 __ bind(&right_smi); 3041 __ bind(&right_smi);
3073 __ SmiToDouble(d1, r3); 3042 __ SmiToDouble(d1, r2);
3074 3043
3075 __ bind(&left); 3044 __ bind(&left);
3076 __ JumpIfSmi(r4, &left_smi); 3045 __ JumpIfSmi(r3, &left_smi);
3077 __ CheckMap(r4, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, 3046 __ CheckMap(r3, r4, Heap::kHeapNumberMapRootIndex, &maybe_undefined2,
3078 DONT_DO_SMI_CHECK); 3047 DONT_DO_SMI_CHECK);
3079 __ lfd(d0, FieldMemOperand(r4, HeapNumber::kValueOffset)); 3048 __ LoadDouble(d0, FieldMemOperand(r3, HeapNumber::kValueOffset));
3080 __ b(&done); 3049 __ b(&done);
3081 __ bind(&left_smi); 3050 __ bind(&left_smi);
3082 __ SmiToDouble(d0, r4); 3051 __ SmiToDouble(d0, r3);
3083 3052
3084 __ bind(&done); 3053 __ bind(&done);
3085 3054
3086 // Compare operands 3055 // Compare operands
3087 __ fcmpu(d0, d1); 3056 __ cdbr(d0, d1);
3088 3057
3089 // Don't base result on status bits when a NaN is involved. 3058 // Don't base result on status bits when a NaN is involved.
3090 __ bunordered(&unordered); 3059 __ bunordered(&unordered);
3091 3060
3092 // Return a result of -1, 0, or 1, based on status bits. 3061 // Return a result of -1, 0, or 1, based on status bits.
3093 if (CpuFeatures::IsSupported(ISELECT)) { 3062 __ beq(&equal);
3094 DCHECK(EQUAL == 0); 3063 __ blt(&less_than);
3095 __ li(r4, Operand(GREATER)); 3064 // assume greater than
3096 __ li(r5, Operand(LESS)); 3065 __ LoadImmP(r2, Operand(GREATER));
3097 __ isel(eq, r3, r0, r4); 3066 __ Ret();
3098 __ isel(lt, r3, r5, r3); 3067 __ bind(&equal);
3099 __ Ret(); 3068 __ LoadImmP(r2, Operand(EQUAL));
3100 } else { 3069 __ Ret();
3101 __ beq(&equal); 3070 __ bind(&less_than);
3102 __ blt(&less_than); 3071 __ LoadImmP(r2, Operand(LESS));
3103 // assume greater than 3072 __ Ret();
3104 __ li(r3, Operand(GREATER));
3105 __ Ret();
3106 __ bind(&equal);
3107 __ li(r3, Operand(EQUAL));
3108 __ Ret();
3109 __ bind(&less_than);
3110 __ li(r3, Operand(LESS));
3111 __ Ret();
3112 }
3113 3073
3114 __ bind(&unordered); 3074 __ bind(&unordered);
3115 __ bind(&generic_stub); 3075 __ bind(&generic_stub);
3116 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, 3076 CompareICStub stub(isolate(), op(), CompareICState::GENERIC,
3117 CompareICState::GENERIC, CompareICState::GENERIC); 3077 CompareICState::GENERIC, CompareICState::GENERIC);
3118 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 3078 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
3119 3079
3120 __ bind(&maybe_undefined1); 3080 __ bind(&maybe_undefined1);
3121 if (Token::IsOrderedRelationalCompareOp(op())) { 3081 if (Token::IsOrderedRelationalCompareOp(op())) {
3122 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); 3082 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
3123 __ bne(&miss); 3083 __ bne(&miss);
3124 __ JumpIfSmi(r4, &unordered); 3084 __ JumpIfSmi(r3, &unordered);
3125 __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE); 3085 __ CompareObjectType(r3, r4, r4, HEAP_NUMBER_TYPE);
3126 __ bne(&maybe_undefined2); 3086 __ bne(&maybe_undefined2);
3127 __ b(&unordered); 3087 __ b(&unordered);
3128 } 3088 }
3129 3089
3130 __ bind(&maybe_undefined2); 3090 __ bind(&maybe_undefined2);
3131 if (Token::IsOrderedRelationalCompareOp(op())) { 3091 if (Token::IsOrderedRelationalCompareOp(op())) {
3132 __ CompareRoot(r4, Heap::kUndefinedValueRootIndex); 3092 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
3133 __ beq(&unordered); 3093 __ beq(&unordered);
3134 } 3094 }
3135 3095
3136 __ bind(&miss); 3096 __ bind(&miss);
3137 GenerateMiss(masm); 3097 GenerateMiss(masm);
3138 } 3098 }
3139 3099
3140
3141 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { 3100 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) {
3142 DCHECK(state() == CompareICState::INTERNALIZED_STRING); 3101 DCHECK(state() == CompareICState::INTERNALIZED_STRING);
3143 Label miss, not_equal; 3102 Label miss, not_equal;
3144 3103
3145 // Registers containing left and right operands respectively. 3104 // Registers containing left and right operands respectively.
3146 Register left = r4; 3105 Register left = r3;
3147 Register right = r3; 3106 Register right = r2;
3148 Register tmp1 = r5; 3107 Register tmp1 = r4;
3149 Register tmp2 = r6; 3108 Register tmp2 = r5;
3150 3109
3151 // Check that both operands are heap objects. 3110 // Check that both operands are heap objects.
3152 __ JumpIfEitherSmi(left, right, &miss); 3111 __ JumpIfEitherSmi(left, right, &miss);
3153 3112
3154 // Check that both operands are symbols. 3113 // Check that both operands are symbols.
3155 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 3114 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3156 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 3115 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3157 __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 3116 __ LoadlB(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3158 __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 3117 __ LoadlB(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3159 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 3118 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3160 __ orx(tmp1, tmp1, tmp2); 3119 __ OrP(tmp1, tmp1, tmp2);
3161 __ andi(r0, tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 3120 __ AndP(r0, tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask));
3162 __ bne(&miss, cr0); 3121 __ bne(&miss);
3163 3122
3164 // Internalized strings are compared by identity. 3123 // Internalized strings are compared by identity.
3165 __ cmp(left, right); 3124 __ CmpP(left, right);
3166 __ bne(&not_equal); 3125 __ bne(&not_equal);
3167 // Make sure r3 is non-zero. At this point input operands are 3126 // Make sure r2 is non-zero. At this point input operands are
3168 // guaranteed to be non-zero. 3127 // guaranteed to be non-zero.
3169 DCHECK(right.is(r3)); 3128 DCHECK(right.is(r2));
3170 STATIC_ASSERT(EQUAL == 0); 3129 STATIC_ASSERT(EQUAL == 0);
3171 STATIC_ASSERT(kSmiTag == 0); 3130 STATIC_ASSERT(kSmiTag == 0);
3172 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 3131 __ LoadSmiLiteral(r2, Smi::FromInt(EQUAL));
3173 __ bind(&not_equal); 3132 __ bind(&not_equal);
3174 __ Ret(); 3133 __ Ret();
3175 3134
3176 __ bind(&miss); 3135 __ bind(&miss);
3177 GenerateMiss(masm); 3136 GenerateMiss(masm);
3178 } 3137 }
3179 3138
3180
3181 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { 3139 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) {
3182 DCHECK(state() == CompareICState::UNIQUE_NAME); 3140 DCHECK(state() == CompareICState::UNIQUE_NAME);
3183 DCHECK(GetCondition() == eq); 3141 DCHECK(GetCondition() == eq);
3184 Label miss; 3142 Label miss;
3185 3143
3186 // Registers containing left and right operands respectively. 3144 // Registers containing left and right operands respectively.
3187 Register left = r4; 3145 Register left = r3;
3188 Register right = r3; 3146 Register right = r2;
3189 Register tmp1 = r5; 3147 Register tmp1 = r4;
3190 Register tmp2 = r6; 3148 Register tmp2 = r5;
3191 3149
3192 // Check that both operands are heap objects. 3150 // Check that both operands are heap objects.
3193 __ JumpIfEitherSmi(left, right, &miss); 3151 __ JumpIfEitherSmi(left, right, &miss);
3194 3152
3195 // Check that both operands are unique names. This leaves the instance 3153 // Check that both operands are unique names. This leaves the instance
3196 // types loaded in tmp1 and tmp2. 3154 // types loaded in tmp1 and tmp2.
3197 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 3155 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3198 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 3156 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3199 __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 3157 __ LoadlB(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3200 __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 3158 __ LoadlB(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3201 3159
3202 __ JumpIfNotUniqueNameInstanceType(tmp1, &miss); 3160 __ JumpIfNotUniqueNameInstanceType(tmp1, &miss);
3203 __ JumpIfNotUniqueNameInstanceType(tmp2, &miss); 3161 __ JumpIfNotUniqueNameInstanceType(tmp2, &miss);
3204 3162
3205 // Unique names are compared by identity. 3163 // Unique names are compared by identity.
3206 __ cmp(left, right); 3164 __ CmpP(left, right);
3207 __ bne(&miss); 3165 __ bne(&miss);
3208 // Make sure r3 is non-zero. At this point input operands are 3166 // Make sure r2 is non-zero. At this point input operands are
3209 // guaranteed to be non-zero. 3167 // guaranteed to be non-zero.
3210 DCHECK(right.is(r3)); 3168 DCHECK(right.is(r2));
3211 STATIC_ASSERT(EQUAL == 0); 3169 STATIC_ASSERT(EQUAL == 0);
3212 STATIC_ASSERT(kSmiTag == 0); 3170 STATIC_ASSERT(kSmiTag == 0);
3213 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 3171 __ LoadSmiLiteral(r2, Smi::FromInt(EQUAL));
3214 __ Ret(); 3172 __ Ret();
3215 3173
3216 __ bind(&miss); 3174 __ bind(&miss);
3217 GenerateMiss(masm); 3175 GenerateMiss(masm);
3218 } 3176 }
3219 3177
3220
3221 void CompareICStub::GenerateStrings(MacroAssembler* masm) { 3178 void CompareICStub::GenerateStrings(MacroAssembler* masm) {
3222 DCHECK(state() == CompareICState::STRING); 3179 DCHECK(state() == CompareICState::STRING);
3223 Label miss, not_identical, is_symbol; 3180 Label miss, not_identical, is_symbol;
3224 3181
3225 bool equality = Token::IsEqualityOp(op()); 3182 bool equality = Token::IsEqualityOp(op());
3226 3183
3227 // Registers containing left and right operands respectively. 3184 // Registers containing left and right operands respectively.
3228 Register left = r4; 3185 Register left = r3;
3229 Register right = r3; 3186 Register right = r2;
3230 Register tmp1 = r5; 3187 Register tmp1 = r4;
3231 Register tmp2 = r6; 3188 Register tmp2 = r5;
3232 Register tmp3 = r7; 3189 Register tmp3 = r6;
3233 Register tmp4 = r8; 3190 Register tmp4 = r7;
3234 3191
3235 // Check that both operands are heap objects. 3192 // Check that both operands are heap objects.
3236 __ JumpIfEitherSmi(left, right, &miss); 3193 __ JumpIfEitherSmi(left, right, &miss);
3237 3194
3238 // Check that both operands are strings. This leaves the instance 3195 // Check that both operands are strings. This leaves the instance
3239 // types loaded in tmp1 and tmp2. 3196 // types loaded in tmp1 and tmp2.
3240 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 3197 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3241 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 3198 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3242 __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 3199 __ LoadlB(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3243 __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 3200 __ LoadlB(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3244 STATIC_ASSERT(kNotStringTag != 0); 3201 STATIC_ASSERT(kNotStringTag != 0);
3245 __ orx(tmp3, tmp1, tmp2); 3202 __ OrP(tmp3, tmp1, tmp2);
3246 __ andi(r0, tmp3, Operand(kIsNotStringMask)); 3203 __ AndP(r0, tmp3, Operand(kIsNotStringMask));
3247 __ bne(&miss, cr0); 3204 __ bne(&miss);
3248 3205
3249 // Fast check for identical strings. 3206 // Fast check for identical strings.
3250 __ cmp(left, right); 3207 __ CmpP(left, right);
3251 STATIC_ASSERT(EQUAL == 0); 3208 STATIC_ASSERT(EQUAL == 0);
3252 STATIC_ASSERT(kSmiTag == 0); 3209 STATIC_ASSERT(kSmiTag == 0);
3253 __ bne(&not_identical); 3210 __ bne(&not_identical);
3254 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); 3211 __ LoadSmiLiteral(r2, Smi::FromInt(EQUAL));
3255 __ Ret(); 3212 __ Ret();
3256 __ bind(&not_identical); 3213 __ bind(&not_identical);
3257 3214
3258 // Handle not identical strings. 3215 // Handle not identical strings.
3259 3216
3260 // Check that both strings are internalized strings. If they are, we're done 3217 // Check that both strings are internalized strings. If they are, we're done
3261 // because we already know they are not identical. We know they are both 3218 // because we already know they are not identical. We know they are both
3262 // strings. 3219 // strings.
3263 if (equality) { 3220 if (equality) {
3264 DCHECK(GetCondition() == eq); 3221 DCHECK(GetCondition() == eq);
3265 STATIC_ASSERT(kInternalizedTag == 0); 3222 STATIC_ASSERT(kInternalizedTag == 0);
3266 __ orx(tmp3, tmp1, tmp2); 3223 __ OrP(tmp3, tmp1, tmp2);
3267 __ andi(r0, tmp3, Operand(kIsNotInternalizedMask)); 3224 __ AndP(r0, tmp3, Operand(kIsNotInternalizedMask));
3268 // Make sure r3 is non-zero. At this point input operands are 3225 __ bne(&is_symbol);
3226 // Make sure r2 is non-zero. At this point input operands are
3269 // guaranteed to be non-zero. 3227 // guaranteed to be non-zero.
3270 DCHECK(right.is(r3)); 3228 DCHECK(right.is(r2));
3271 __ Ret(eq, cr0); 3229 __ Ret();
3230 __ bind(&is_symbol);
3272 } 3231 }
3273 3232
3274 // Check that both strings are sequential one-byte. 3233 // Check that both strings are sequential one-byte.
3275 Label runtime; 3234 Label runtime;
3276 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, 3235 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4,
3277 &runtime); 3236 &runtime);
3278 3237
3279 // Compare flat one-byte strings. Returns when done. 3238 // Compare flat one-byte strings. Returns when done.
3280 if (equality) { 3239 if (equality) {
3281 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, 3240 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1,
3282 tmp2); 3241 tmp2);
3283 } else { 3242 } else {
3284 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1, 3243 StringHelper::GenerateCompareFlatOneByteStrings(masm, left, right, tmp1,
3285 tmp2, tmp3); 3244 tmp2, tmp3);
3286 } 3245 }
3287 3246
3288 // Handle more complex cases in runtime. 3247 // Handle more complex cases in runtime.
3289 __ bind(&runtime); 3248 __ bind(&runtime);
3290 __ Push(left, right); 3249 __ Push(left, right);
3291 if (equality) { 3250 if (equality) {
3292 __ TailCallRuntime(Runtime::kStringEquals); 3251 __ TailCallRuntime(Runtime::kStringEquals);
3293 } else { 3252 } else {
3294 __ TailCallRuntime(Runtime::kStringCompare); 3253 __ TailCallRuntime(Runtime::kStringCompare);
3295 } 3254 }
3296 3255
3297 __ bind(&miss); 3256 __ bind(&miss);
3298 GenerateMiss(masm); 3257 GenerateMiss(masm);
3299 } 3258 }
3300 3259
3301
3302 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { 3260 void CompareICStub::GenerateReceivers(MacroAssembler* masm) {
3303 DCHECK_EQ(CompareICState::RECEIVER, state()); 3261 DCHECK_EQ(CompareICState::RECEIVER, state());
3304 Label miss; 3262 Label miss;
3305 __ and_(r5, r4, r3); 3263 __ AndP(r4, r3, r2);
3306 __ JumpIfSmi(r5, &miss); 3264 __ JumpIfSmi(r4, &miss);
3307 3265
3308 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); 3266 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
3309 __ CompareObjectType(r3, r5, r5, FIRST_JS_RECEIVER_TYPE); 3267 __ CompareObjectType(r2, r4, r4, FIRST_JS_RECEIVER_TYPE);
3310 __ blt(&miss); 3268 __ blt(&miss);
3311 __ CompareObjectType(r4, r5, r5, FIRST_JS_RECEIVER_TYPE); 3269 __ CompareObjectType(r3, r4, r4, FIRST_JS_RECEIVER_TYPE);
3312 __ blt(&miss); 3270 __ blt(&miss);
3313 3271
3314 DCHECK(GetCondition() == eq); 3272 DCHECK(GetCondition() == eq);
3315 __ sub(r3, r3, r4); 3273 __ SubP(r2, r2, r3);
3316 __ Ret(); 3274 __ Ret();
3317 3275
3318 __ bind(&miss); 3276 __ bind(&miss);
3319 GenerateMiss(masm); 3277 GenerateMiss(masm);
3320 } 3278 }
3321 3279
3322
3323 void CompareICStub::GenerateKnownReceivers(MacroAssembler* masm) { 3280 void CompareICStub::GenerateKnownReceivers(MacroAssembler* masm) {
3324 Label miss; 3281 Label miss;
3325 Handle<WeakCell> cell = Map::WeakCellForMap(known_map_); 3282 Handle<WeakCell> cell = Map::WeakCellForMap(known_map_);
3326 __ and_(r5, r4, r3); 3283 __ AndP(r4, r3, r2);
3327 __ JumpIfSmi(r5, &miss); 3284 __ JumpIfSmi(r4, &miss);
3328 __ GetWeakValue(r7, cell); 3285 __ GetWeakValue(r6, cell);
3286 __ LoadP(r4, FieldMemOperand(r2, HeapObject::kMapOffset));
3329 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset)); 3287 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
3330 __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset)); 3288 __ CmpP(r4, r6);
3331 __ cmp(r5, r7);
3332 __ bne(&miss); 3289 __ bne(&miss);
3333 __ cmp(r6, r7); 3290 __ CmpP(r5, r6);
3334 __ bne(&miss); 3291 __ bne(&miss);
3335 3292
3336 if (Token::IsEqualityOp(op())) { 3293 if (Token::IsEqualityOp(op())) {
3337 __ sub(r3, r3, r4); 3294 __ SubP(r2, r2, r3);
3338 __ Ret(); 3295 __ Ret();
3339 } else { 3296 } else {
3340 if (op() == Token::LT || op() == Token::LTE) { 3297 if (op() == Token::LT || op() == Token::LTE) {
3341 __ LoadSmiLiteral(r5, Smi::FromInt(GREATER)); 3298 __ LoadSmiLiteral(r4, Smi::FromInt(GREATER));
3342 } else { 3299 } else {
3343 __ LoadSmiLiteral(r5, Smi::FromInt(LESS)); 3300 __ LoadSmiLiteral(r4, Smi::FromInt(LESS));
3344 } 3301 }
3345 __ Push(r4, r3, r5); 3302 __ Push(r3, r2, r4);
3346 __ TailCallRuntime(Runtime::kCompare); 3303 __ TailCallRuntime(Runtime::kCompare);
3347 } 3304 }
3348 3305
3349 __ bind(&miss); 3306 __ bind(&miss);
3350 GenerateMiss(masm); 3307 GenerateMiss(masm);
3351 } 3308 }
3352 3309
3353
3354 void CompareICStub::GenerateMiss(MacroAssembler* masm) { 3310 void CompareICStub::GenerateMiss(MacroAssembler* masm) {
3355 { 3311 {
3356 // Call the runtime system in a fresh internal frame. 3312 // Call the runtime system in a fresh internal frame.
3357 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 3313 FrameScope scope(masm, StackFrame::INTERNAL);
3358 __ Push(r4, r3); 3314 __ Push(r3, r2);
3359 __ Push(r4, r3); 3315 __ Push(r3, r2);
3360 __ LoadSmiLiteral(r0, Smi::FromInt(op())); 3316 __ LoadSmiLiteral(r0, Smi::FromInt(op()));
3361 __ push(r0); 3317 __ push(r0);
3362 __ CallRuntime(Runtime::kCompareIC_Miss); 3318 __ CallRuntime(Runtime::kCompareIC_Miss);
3363 // Compute the entry point of the rewritten stub. 3319 // Compute the entry point of the rewritten stub.
3364 __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); 3320 __ AddP(r4, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
3365 // Restore registers. 3321 // Restore registers.
3366 __ Pop(r4, r3); 3322 __ Pop(r3, r2);
3367 } 3323 }
3368 3324
3369 __ JumpToJSEntry(r5); 3325 __ JumpToJSEntry(r4);
3370 } 3326 }
3371 3327
3372
3373 // This stub is paired with DirectCEntryStub::GenerateCall 3328 // This stub is paired with DirectCEntryStub::GenerateCall
3374 void DirectCEntryStub::Generate(MacroAssembler* masm) { 3329 void DirectCEntryStub::Generate(MacroAssembler* masm) {
3375 // Place the return address on the stack, making the call 3330 __ CleanseP(r14);
3376 // GC safe. The RegExp backend also relies on this. 3331
3377 __ mflr(r0); 3332 // Statement positions are expected to be recorded when the target
3378 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 3333 // address is loaded.
3379 __ Call(ip); // Call the C++ function. 3334 __ positions_recorder()->WriteRecordedPositions();
3380 __ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); 3335
3381 __ mtlr(r0); 3336 __ b(ip); // Callee will return to R14 directly
3382 __ blr();
3383 } 3337 }
3384 3338
3339 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) {
3340 #if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
3341 // Native AIX/S390X Linux use a function descriptor.
3342 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
3343 __ LoadP(target, MemOperand(target, 0)); // Instruction address
3344 #else
3345 // ip needs to be set for DirectCEentryStub::Generate, and also
3346 // for ABI_CALL_VIA_IP.
3347 __ Move(ip, target);
3348 #endif
3385 3349
3386 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, Register target) { 3350 __ call(GetCode(), RelocInfo::CODE_TARGET); // Call the stub.
3387 if (ABI_USES_FUNCTION_DESCRIPTORS) {
3388 // AIX/PPC64BE Linux use a function descriptor.
3389 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
3390 __ LoadP(ip, MemOperand(target, 0)); // Instruction address
3391 } else {
3392 // ip needs to be set for DirectCEentryStub::Generate, and also
3393 // for ABI_CALL_VIA_IP.
3394 __ Move(ip, target);
3395 }
3396
3397 intptr_t code = reinterpret_cast<intptr_t>(GetCode().location());
3398 __ mov(r0, Operand(code, RelocInfo::CODE_TARGET));
3399 __ Call(r0); // Call the stub.
3400 } 3351 }
3401 3352
3402
3403 void NameDictionaryLookupStub::GenerateNegativeLookup( 3353 void NameDictionaryLookupStub::GenerateNegativeLookup(
3404 MacroAssembler* masm, Label* miss, Label* done, Register receiver, 3354 MacroAssembler* masm, Label* miss, Label* done, Register receiver,
3405 Register properties, Handle<Name> name, Register scratch0) { 3355 Register properties, Handle<Name> name, Register scratch0) {
3406 DCHECK(name->IsUniqueName()); 3356 DCHECK(name->IsUniqueName());
3407 // If names of slots in range from 1 to kProbes - 1 for the hash value are 3357 // If names of slots in range from 1 to kProbes - 1 for the hash value are
3408 // not equal to the name and kProbes-th slot is not used (its name is the 3358 // not equal to the name and kProbes-th slot is not used (its name is the
3409 // undefined value), it guarantees the hash table doesn't contain the 3359 // undefined value), it guarantees the hash table doesn't contain the
3410 // property. It's true even if some slots represent deleted properties 3360 // property. It's true even if some slots represent deleted properties
3411 // (their names are the hole value). 3361 // (their names are the hole value).
3412 for (int i = 0; i < kInlinedProbes; i++) { 3362 for (int i = 0; i < kInlinedProbes; i++) {
3413 // scratch0 points to properties hash. 3363 // scratch0 points to properties hash.
3414 // Compute the masked index: (hash + i + i * i) & mask. 3364 // Compute the masked index: (hash + i + i * i) & mask.
3415 Register index = scratch0; 3365 Register index = scratch0;
3416 // Capacity is smi 2^n. 3366 // Capacity is smi 2^n.
3417 __ LoadP(index, FieldMemOperand(properties, kCapacityOffset)); 3367 __ LoadP(index, FieldMemOperand(properties, kCapacityOffset));
3418 __ subi(index, index, Operand(1)); 3368 __ SubP(index, Operand(1));
3419 __ LoadSmiLiteral( 3369 __ LoadSmiLiteral(
3420 ip, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))); 3370 ip, Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i)));
3421 __ and_(index, index, ip); 3371 __ AndP(index, ip);
3422 3372
3423 // Scale the index by multiplying by the entry size. 3373 // Scale the index by multiplying by the entry size.
3424 STATIC_ASSERT(NameDictionary::kEntrySize == 3); 3374 STATIC_ASSERT(NameDictionary::kEntrySize == 3);
3425 __ ShiftLeftImm(ip, index, Operand(1)); 3375 __ ShiftLeftP(ip, index, Operand(1));
3426 __ add(index, index, ip); // index *= 3. 3376 __ AddP(index, ip); // index *= 3.
3427 3377
3428 Register entity_name = scratch0; 3378 Register entity_name = scratch0;
3429 // Having undefined at this place means the name is not contained. 3379 // Having undefined at this place means the name is not contained.
3430 Register tmp = properties; 3380 Register tmp = properties;
3431 __ SmiToPtrArrayOffset(ip, index); 3381 __ SmiToPtrArrayOffset(ip, index);
3432 __ add(tmp, properties, ip); 3382 __ AddP(tmp, properties, ip);
3433 __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 3383 __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
3434 3384
3435 DCHECK(!tmp.is(entity_name)); 3385 DCHECK(!tmp.is(entity_name));
3436 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 3386 __ CompareRoot(entity_name, Heap::kUndefinedValueRootIndex);
3437 __ cmp(entity_name, tmp);
3438 __ beq(done); 3387 __ beq(done);
3439 3388
3440 // Load the hole ready for use below:
3441 __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
3442
3443 // Stop if found the property. 3389 // Stop if found the property.
3444 __ Cmpi(entity_name, Operand(Handle<Name>(name)), r0); 3390 __ CmpP(entity_name, Operand(Handle<Name>(name)));
3445 __ beq(miss); 3391 __ beq(miss);
3446 3392
3447 Label good; 3393 Label good;
3448 __ cmp(entity_name, tmp); 3394 __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex);
3449 __ beq(&good); 3395 __ beq(&good);
3450 3396
3451 // Check if the entry name is not a unique name. 3397 // Check if the entry name is not a unique name.
3452 __ LoadP(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 3398 __ LoadP(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
3453 __ lbz(entity_name, FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 3399 __ LoadlB(entity_name,
3400 FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
3454 __ JumpIfNotUniqueNameInstanceType(entity_name, miss); 3401 __ JumpIfNotUniqueNameInstanceType(entity_name, miss);
3455 __ bind(&good); 3402 __ bind(&good);
3456 3403
3457 // Restore the properties. 3404 // Restore the properties.
3458 __ LoadP(properties, 3405 __ LoadP(properties,
3459 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 3406 FieldMemOperand(receiver, JSObject::kPropertiesOffset));
3460 } 3407 }
3461 3408
3462 const int spill_mask = (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() | 3409 const int spill_mask = (r0.bit() | r8.bit() | r7.bit() | r6.bit() | r5.bit() |
3463 r5.bit() | r4.bit() | r3.bit()); 3410 r4.bit() | r3.bit() | r2.bit());
3464 3411
3465 __ mflr(r0); 3412 __ LoadRR(r0, r14);
3466 __ MultiPush(spill_mask); 3413 __ MultiPush(spill_mask);
3467 3414
3468 __ LoadP(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 3415 __ LoadP(r2, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
3469 __ mov(r4, Operand(Handle<Name>(name))); 3416 __ mov(r3, Operand(Handle<Name>(name)));
3470 NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP); 3417 NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP);
3471 __ CallStub(&stub); 3418 __ CallStub(&stub);
3472 __ cmpi(r3, Operand::Zero()); 3419 __ CmpP(r2, Operand::Zero());
3473 3420
3474 __ MultiPop(spill_mask); // MultiPop does not touch condition flags 3421 __ MultiPop(spill_mask); // MultiPop does not touch condition flags
3475 __ mtlr(r0); 3422 __ LoadRR(r14, r0);
3476 3423
3477 __ beq(done); 3424 __ beq(done);
3478 __ bne(miss); 3425 __ bne(miss);
3479 } 3426 }
3480 3427
3481
3482 // Probe the name dictionary in the |elements| register. Jump to the 3428 // Probe the name dictionary in the |elements| register. Jump to the
3483 // |done| label if a property with the given name is found. Jump to 3429 // |done| label if a property with the given name is found. Jump to
3484 // the |miss| label otherwise. 3430 // the |miss| label otherwise.
3485 // If lookup was successful |scratch2| will be equal to elements + 4 * index. 3431 // If lookup was successful |scratch2| will be equal to elements + 4 * index.
3486 void NameDictionaryLookupStub::GeneratePositiveLookup( 3432 void NameDictionaryLookupStub::GeneratePositiveLookup(
3487 MacroAssembler* masm, Label* miss, Label* done, Register elements, 3433 MacroAssembler* masm, Label* miss, Label* done, Register elements,
3488 Register name, Register scratch1, Register scratch2) { 3434 Register name, Register scratch1, Register scratch2) {
3489 DCHECK(!elements.is(scratch1)); 3435 DCHECK(!elements.is(scratch1));
3490 DCHECK(!elements.is(scratch2)); 3436 DCHECK(!elements.is(scratch2));
3491 DCHECK(!name.is(scratch1)); 3437 DCHECK(!name.is(scratch1));
3492 DCHECK(!name.is(scratch2)); 3438 DCHECK(!name.is(scratch2));
3493 3439
3494 __ AssertName(name); 3440 __ AssertName(name);
3495 3441
3496 // Compute the capacity mask. 3442 // Compute the capacity mask.
3497 __ LoadP(scratch1, FieldMemOperand(elements, kCapacityOffset)); 3443 __ LoadP(scratch1, FieldMemOperand(elements, kCapacityOffset));
3498 __ SmiUntag(scratch1); // convert smi to int 3444 __ SmiUntag(scratch1); // convert smi to int
3499 __ subi(scratch1, scratch1, Operand(1)); 3445 __ SubP(scratch1, Operand(1));
3500 3446
3501 // Generate an unrolled loop that performs a few probes before 3447 // Generate an unrolled loop that performs a few probes before
3502 // giving up. Measurements done on Gmail indicate that 2 probes 3448 // giving up. Measurements done on Gmail indicate that 2 probes
3503 // cover ~93% of loads from dictionaries. 3449 // cover ~93% of loads from dictionaries.
3504 for (int i = 0; i < kInlinedProbes; i++) { 3450 for (int i = 0; i < kInlinedProbes; i++) {
3505 // Compute the masked index: (hash + i + i * i) & mask. 3451 // Compute the masked index: (hash + i + i * i) & mask.
3506 __ lwz(scratch2, FieldMemOperand(name, Name::kHashFieldOffset)); 3452 __ LoadlW(scratch2, FieldMemOperand(name, String::kHashFieldOffset));
3507 if (i > 0) { 3453 if (i > 0) {
3508 // Add the probe offset (i + i * i) left shifted to avoid right shifting 3454 // Add the probe offset (i + i * i) left shifted to avoid right shifting
3509 // the hash in a separate instruction. The value hash + i + i * i is right 3455 // the hash in a separate instruction. The value hash + i + i * i is right
3510 // shifted in the following and instruction. 3456 // shifted in the following and instruction.
3511 DCHECK(NameDictionary::GetProbeOffset(i) < 3457 DCHECK(NameDictionary::GetProbeOffset(i) <
3512 1 << (32 - Name::kHashFieldOffset)); 3458 1 << (32 - Name::kHashFieldOffset));
3513 __ addi(scratch2, scratch2, 3459 __ AddP(scratch2,
3514 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 3460 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift));
3515 } 3461 }
3516 __ srwi(scratch2, scratch2, Operand(Name::kHashShift)); 3462 __ srl(scratch2, Operand(String::kHashShift));
3517 __ and_(scratch2, scratch1, scratch2); 3463 __ AndP(scratch2, scratch1);
3518 3464
3519 // Scale the index by multiplying by the entry size. 3465 // Scale the index by multiplying by the entry size.
3520 STATIC_ASSERT(NameDictionary::kEntrySize == 3); 3466 STATIC_ASSERT(NameDictionary::kEntrySize == 3);
3521 // scratch2 = scratch2 * 3. 3467 // scratch2 = scratch2 * 3.
3522 __ ShiftLeftImm(ip, scratch2, Operand(1)); 3468 __ ShiftLeftP(ip, scratch2, Operand(1));
3523 __ add(scratch2, scratch2, ip); 3469 __ AddP(scratch2, ip);
3524 3470
3525 // Check if the key is identical to the name. 3471 // Check if the key is identical to the name.
3526 __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2)); 3472 __ ShiftLeftP(ip, scratch2, Operand(kPointerSizeLog2));
3527 __ add(scratch2, elements, ip); 3473 __ AddP(scratch2, elements, ip);
3528 __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset)); 3474 __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset));
3529 __ cmp(name, ip); 3475 __ CmpP(name, ip);
3530 __ beq(done); 3476 __ beq(done);
3531 } 3477 }
3532 3478
3533 const int spill_mask = (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() | 3479 const int spill_mask = (r0.bit() | r8.bit() | r7.bit() | r6.bit() | r5.bit() |
3534 r5.bit() | r4.bit() | r3.bit()) & 3480 r4.bit() | r3.bit() | r2.bit()) &
3535 ~(scratch1.bit() | scratch2.bit()); 3481 ~(scratch1.bit() | scratch2.bit());
3536 3482
3537 __ mflr(r0); 3483 __ LoadRR(r0, r14);
3538 __ MultiPush(spill_mask); 3484 __ MultiPush(spill_mask);
3539 if (name.is(r3)) { 3485 if (name.is(r2)) {
3540 DCHECK(!elements.is(r4)); 3486 DCHECK(!elements.is(r3));
3541 __ mr(r4, name); 3487 __ LoadRR(r3, name);
3542 __ mr(r3, elements); 3488 __ LoadRR(r2, elements);
3543 } else { 3489 } else {
3544 __ mr(r3, elements); 3490 __ LoadRR(r2, elements);
3545 __ mr(r4, name); 3491 __ LoadRR(r3, name);
3546 } 3492 }
3547 NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP); 3493 NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP);
3548 __ CallStub(&stub); 3494 __ CallStub(&stub);
3549 __ cmpi(r3, Operand::Zero()); 3495 __ LoadRR(r1, r2);
3550 __ mr(scratch2, r5); 3496 __ LoadRR(scratch2, r4);
3551 __ MultiPop(spill_mask); 3497 __ MultiPop(spill_mask);
3552 __ mtlr(r0); 3498 __ LoadRR(r14, r0);
3553 3499
3500 __ CmpP(r1, Operand::Zero());
3554 __ bne(done); 3501 __ bne(done);
3555 __ beq(miss); 3502 __ beq(miss);
3556 } 3503 }
3557 3504
3558
3559 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 3505 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
3560 // This stub overrides SometimesSetsUpAFrame() to return false. That means 3506 // This stub overrides SometimesSetsUpAFrame() to return false. That means
3561 // we cannot call anything that could cause a GC from this stub. 3507 // we cannot call anything that could cause a GC from this stub.
3562 // Registers: 3508 // Registers:
3563 // result: NameDictionary to probe 3509 // result: NameDictionary to probe
3564 // r4: key 3510 // r3: key
3565 // dictionary: NameDictionary to probe. 3511 // dictionary: NameDictionary to probe.
3566 // index: will hold an index of entry if lookup is successful. 3512 // index: will hold an index of entry if lookup is successful.
3567 // might alias with result_. 3513 // might alias with result_.
3568 // Returns: 3514 // Returns:
3569 // result_ is zero if lookup failed, non zero otherwise. 3515 // result_ is zero if lookup failed, non zero otherwise.
3570 3516
3571 Register result = r3; 3517 Register result = r2;
3572 Register dictionary = r3; 3518 Register dictionary = r2;
3573 Register key = r4; 3519 Register key = r3;
3574 Register index = r5; 3520 Register index = r4;
3575 Register mask = r6; 3521 Register mask = r5;
3576 Register hash = r7; 3522 Register hash = r6;
3577 Register undefined = r8; 3523 Register undefined = r7;
3578 Register entry_key = r9; 3524 Register entry_key = r8;
3579 Register scratch = r9; 3525 Register scratch = r8;
3580 3526
3581 Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 3527 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
3582 3528
3583 __ LoadP(mask, FieldMemOperand(dictionary, kCapacityOffset)); 3529 __ LoadP(mask, FieldMemOperand(dictionary, kCapacityOffset));
3584 __ SmiUntag(mask); 3530 __ SmiUntag(mask);
3585 __ subi(mask, mask, Operand(1)); 3531 __ SubP(mask, Operand(1));
3586 3532
3587 __ lwz(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 3533 __ LoadlW(hash, FieldMemOperand(key, String::kHashFieldOffset));
3588 3534
3589 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 3535 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
3590 3536
3591 for (int i = kInlinedProbes; i < kTotalProbes; i++) { 3537 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
3592 // Compute the masked index: (hash + i + i * i) & mask. 3538 // Compute the masked index: (hash + i + i * i) & mask.
3593 // Capacity is smi 2^n. 3539 // Capacity is smi 2^n.
3594 if (i > 0) { 3540 if (i > 0) {
3595 // Add the probe offset (i + i * i) left shifted to avoid right shifting 3541 // Add the probe offset (i + i * i) left shifted to avoid right shifting
3596 // the hash in a separate instruction. The value hash + i + i * i is right 3542 // the hash in a separate instruction. The value hash + i + i * i is right
3597 // shifted in the following and instruction. 3543 // shifted in the following and instruction.
3598 DCHECK(NameDictionary::GetProbeOffset(i) < 3544 DCHECK(NameDictionary::GetProbeOffset(i) <
3599 1 << (32 - Name::kHashFieldOffset)); 3545 1 << (32 - Name::kHashFieldOffset));
3600 __ addi(index, hash, 3546 __ AddP(index, hash,
3601 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 3547 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift));
3602 } else { 3548 } else {
3603 __ mr(index, hash); 3549 __ LoadRR(index, hash);
3604 } 3550 }
3605 __ srwi(r0, index, Operand(Name::kHashShift)); 3551 __ ShiftRight(r0, index, Operand(String::kHashShift));
3606 __ and_(index, mask, r0); 3552 __ AndP(index, r0, mask);
3607 3553
3608 // Scale the index by multiplying by the entry size. 3554 // Scale the index by multiplying by the entry size.
3609 STATIC_ASSERT(NameDictionary::kEntrySize == 3); 3555 STATIC_ASSERT(NameDictionary::kEntrySize == 3);
3610 __ ShiftLeftImm(scratch, index, Operand(1)); 3556 __ ShiftLeftP(scratch, index, Operand(1));
3611 __ add(index, index, scratch); // index *= 3. 3557 __ AddP(index, scratch); // index *= 3.
3612 3558
3613 __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2)); 3559 __ ShiftLeftP(scratch, index, Operand(kPointerSizeLog2));
3614 __ add(index, dictionary, scratch); 3560 __ AddP(index, dictionary, scratch);
3615 __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset)); 3561 __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset));
3616 3562
3617 // Having undefined at this place means the name is not contained. 3563 // Having undefined at this place means the name is not contained.
3618 __ cmp(entry_key, undefined); 3564 __ CmpP(entry_key, undefined);
3619 __ beq(&not_in_dictionary); 3565 __ beq(&not_in_dictionary);
3620 3566
3621 // Stop if found the property. 3567 // Stop if found the property.
3622 __ cmp(entry_key, key); 3568 __ CmpP(entry_key, key);
3623 __ beq(&in_dictionary); 3569 __ beq(&in_dictionary);
3624 3570
3625 if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) { 3571 if (i != kTotalProbes - 1 && mode() == NEGATIVE_LOOKUP) {
3626 // Check if the entry name is not a unique name. 3572 // Check if the entry name is not a unique name.
3627 __ LoadP(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 3573 __ LoadP(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
3628 __ lbz(entry_key, FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 3574 __ LoadlB(entry_key,
3575 FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
3629 __ JumpIfNotUniqueNameInstanceType(entry_key, &maybe_in_dictionary); 3576 __ JumpIfNotUniqueNameInstanceType(entry_key, &maybe_in_dictionary);
3630 } 3577 }
3631 } 3578 }
3632 3579
3633 __ bind(&maybe_in_dictionary); 3580 __ bind(&maybe_in_dictionary);
3634 // If we are doing negative lookup then probing failure should be 3581 // If we are doing negative lookup then probing failure should be
3635 // treated as a lookup success. For positive lookup probing failure 3582 // treated as a lookup success. For positive lookup probing failure
3636 // should be treated as lookup failure. 3583 // should be treated as lookup failure.
3637 if (mode() == POSITIVE_LOOKUP) { 3584 if (mode() == POSITIVE_LOOKUP) {
3638 __ li(result, Operand::Zero()); 3585 __ LoadImmP(result, Operand::Zero());
3639 __ Ret(); 3586 __ Ret();
3640 } 3587 }
3641 3588
3642 __ bind(&in_dictionary); 3589 __ bind(&in_dictionary);
3643 __ li(result, Operand(1)); 3590 __ LoadImmP(result, Operand(1));
3644 __ Ret(); 3591 __ Ret();
3645 3592
3646 __ bind(&not_in_dictionary); 3593 __ bind(&not_in_dictionary);
3647 __ li(result, Operand::Zero()); 3594 __ LoadImmP(result, Operand::Zero());
3648 __ Ret(); 3595 __ Ret();
3649 } 3596 }
3650 3597
3651
3652 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 3598 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
3653 Isolate* isolate) { 3599 Isolate* isolate) {
3654 StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); 3600 StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs);
3655 stub1.GetCode(); 3601 stub1.GetCode();
3656 // Hydrogen code stubs need stub2 at snapshot time. 3602 // Hydrogen code stubs need stub2 at snapshot time.
3657 StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 3603 StoreBufferOverflowStub stub2(isolate, kSaveFPRegs);
3658 stub2.GetCode(); 3604 stub2.GetCode();
3659 } 3605 }
3660 3606
3661
3662 // Takes the input in 3 registers: address_ value_ and object_. A pointer to 3607 // Takes the input in 3 registers: address_ value_ and object_. A pointer to
3663 // the value has just been written into the object, now this stub makes sure 3608 // the value has just been written into the object, now this stub makes sure
3664 // we keep the GC informed. The word in the object where the value has been 3609 // we keep the GC informed. The word in the object where the value has been
3665 // written is in the address register. 3610 // written is in the address register.
3666 void RecordWriteStub::Generate(MacroAssembler* masm) { 3611 void RecordWriteStub::Generate(MacroAssembler* masm) {
3667 Label skip_to_incremental_noncompacting; 3612 Label skip_to_incremental_noncompacting;
3668 Label skip_to_incremental_compacting; 3613 Label skip_to_incremental_compacting;
3669 3614
3670 // The first two branch instructions are generated with labels so as to 3615 // The first two branch instructions are generated with labels so as to
3671 // get the offset fixed up correctly by the bind(Label*) call. We patch 3616 // get the offset fixed up correctly by the bind(Label*) call. We patch
3672 // it back and forth between branch condition True and False 3617 // it back and forth between branch condition True and False
3673 // when we start and stop incremental heap marking. 3618 // when we start and stop incremental heap marking.
3674 // See RecordWriteStub::Patch for details. 3619 // See RecordWriteStub::Patch for details.
3675 3620
3676 // Clear the bit, branch on True for NOP action initially 3621 // Clear the bit, branch on True for NOP action initially
3677 __ crclr(Assembler::encode_crbit(cr2, CR_LT)); 3622 __ b(CC_NOP, &skip_to_incremental_noncompacting);
3678 __ blt(&skip_to_incremental_noncompacting, cr2); 3623 __ b(CC_NOP, &skip_to_incremental_compacting);
3679 __ blt(&skip_to_incremental_compacting, cr2);
3680 3624
3681 if (remembered_set_action() == EMIT_REMEMBERED_SET) { 3625 if (remembered_set_action() == EMIT_REMEMBERED_SET) {
3682 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3626 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
3683 MacroAssembler::kReturnAtEnd); 3627 MacroAssembler::kReturnAtEnd);
3684 } 3628 }
3685 __ Ret(); 3629 __ Ret();
3686 3630
3687 __ bind(&skip_to_incremental_noncompacting); 3631 __ bind(&skip_to_incremental_noncompacting);
3688 GenerateIncremental(masm, INCREMENTAL); 3632 GenerateIncremental(masm, INCREMENTAL);
3689 3633
3690 __ bind(&skip_to_incremental_compacting); 3634 __ bind(&skip_to_incremental_compacting);
3691 GenerateIncremental(masm, INCREMENTAL_COMPACTION); 3635 GenerateIncremental(masm, INCREMENTAL_COMPACTION);
3692 3636
3693 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 3637 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
3694 // Will be checked in IncrementalMarking::ActivateGeneratedStub. 3638 // Will be checked in IncrementalMarking::ActivateGeneratedStub.
3695 // patching not required on PPC as the initial path is effectively NOP 3639 // patching not required on S390 as the initial path is effectively NOP
3696 } 3640 }
3697 3641
3698
3699 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 3642 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
3700 regs_.Save(masm); 3643 regs_.Save(masm);
3701 3644
3702 if (remembered_set_action() == EMIT_REMEMBERED_SET) { 3645 if (remembered_set_action() == EMIT_REMEMBERED_SET) {
3703 Label dont_need_remembered_set; 3646 Label dont_need_remembered_set;
3704 3647
3705 __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0)); 3648 __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0));
3706 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 3649 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value.
3707 regs_.scratch0(), &dont_need_remembered_set); 3650 regs_.scratch0(), &dont_need_remembered_set);
3708 3651
(...skipping 12 matching lines...) Expand all
3721 __ bind(&dont_need_remembered_set); 3664 __ bind(&dont_need_remembered_set);
3722 } 3665 }
3723 3666
3724 CheckNeedsToInformIncrementalMarker( 3667 CheckNeedsToInformIncrementalMarker(
3725 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); 3668 masm, kReturnOnNoNeedToInformIncrementalMarker, mode);
3726 InformIncrementalMarker(masm); 3669 InformIncrementalMarker(masm);
3727 regs_.Restore(masm); 3670 regs_.Restore(masm);
3728 __ Ret(); 3671 __ Ret();
3729 } 3672 }
3730 3673
3731
3732 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 3674 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) {
3733 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode()); 3675 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode());
3734 int argument_count = 3; 3676 int argument_count = 3;
3735 __ PrepareCallCFunction(argument_count, regs_.scratch0()); 3677 __ PrepareCallCFunction(argument_count, regs_.scratch0());
3736 Register address = 3678 Register address =
3737 r3.is(regs_.address()) ? regs_.scratch0() : regs_.address(); 3679 r2.is(regs_.address()) ? regs_.scratch0() : regs_.address();
3738 DCHECK(!address.is(regs_.object())); 3680 DCHECK(!address.is(regs_.object()));
3739 DCHECK(!address.is(r3)); 3681 DCHECK(!address.is(r2));
3740 __ mr(address, regs_.address()); 3682 __ LoadRR(address, regs_.address());
3741 __ mr(r3, regs_.object()); 3683 __ LoadRR(r2, regs_.object());
3742 __ mr(r4, address); 3684 __ LoadRR(r3, address);
3743 __ mov(r5, Operand(ExternalReference::isolate_address(isolate()))); 3685 __ mov(r4, Operand(ExternalReference::isolate_address(isolate())));
3744 3686
3745 AllowExternalCallThatCantCauseGC scope(masm); 3687 AllowExternalCallThatCantCauseGC scope(masm);
3746 __ CallCFunction( 3688 __ CallCFunction(
3747 ExternalReference::incremental_marking_record_write_function(isolate()), 3689 ExternalReference::incremental_marking_record_write_function(isolate()),
3748 argument_count); 3690 argument_count);
3749 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode()); 3691 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode());
3750 } 3692 }
3751 3693
3752
3753 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( 3694 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
3754 MacroAssembler* masm, OnNoNeedToInformIncrementalMarker on_no_need, 3695 MacroAssembler* masm, OnNoNeedToInformIncrementalMarker on_no_need,
3755 Mode mode) { 3696 Mode mode) {
3756 Label on_black; 3697 Label on_black;
3757 Label need_incremental; 3698 Label need_incremental;
3758 Label need_incremental_pop_scratch; 3699 Label need_incremental_pop_scratch;
3759 3700
3760 DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0); 3701 DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
3761 __ lis(r0, Operand((~Page::kPageAlignmentMask >> 16))); 3702 __ AndP(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask));
3762 __ and_(regs_.scratch0(), regs_.object(), r0);
3763 __ LoadP( 3703 __ LoadP(
3764 regs_.scratch1(), 3704 regs_.scratch1(),
3765 MemOperand(regs_.scratch0(), MemoryChunk::kWriteBarrierCounterOffset)); 3705 MemOperand(regs_.scratch0(), MemoryChunk::kWriteBarrierCounterOffset));
3766 __ subi(regs_.scratch1(), regs_.scratch1(), Operand(1)); 3706 __ SubP(regs_.scratch1(), regs_.scratch1(), Operand(1));
3767 __ StoreP( 3707 __ StoreP(
3768 regs_.scratch1(), 3708 regs_.scratch1(),
3769 MemOperand(regs_.scratch0(), MemoryChunk::kWriteBarrierCounterOffset)); 3709 MemOperand(regs_.scratch0(), MemoryChunk::kWriteBarrierCounterOffset));
3770 __ cmpi(regs_.scratch1(), Operand::Zero()); // PPC, we could do better here 3710 __ CmpP(regs_.scratch1(), Operand::Zero()); // S390, we could do better here
3771 __ blt(&need_incremental); 3711 __ blt(&need_incremental);
3772 3712
3773 // Let's look at the color of the object: If it is not black we don't have 3713 // Let's look at the color of the object: If it is not black we don't have
3774 // to inform the incremental marker. 3714 // to inform the incremental marker.
3775 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); 3715 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black);
3776 3716
3777 regs_.Restore(masm); 3717 regs_.Restore(masm);
3778 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 3718 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
3779 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(), 3719 __ RememberedSetHelper(object(), address(), value(), save_fp_regs_mode(),
3780 MacroAssembler::kReturnAtEnd); 3720 MacroAssembler::kReturnAtEnd);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3822 } 3762 }
3823 3763
3824 __ bind(&need_incremental_pop_scratch); 3764 __ bind(&need_incremental_pop_scratch);
3825 __ Pop(regs_.object(), regs_.address()); 3765 __ Pop(regs_.object(), regs_.address());
3826 3766
3827 __ bind(&need_incremental); 3767 __ bind(&need_incremental);
3828 3768
3829 // Fall through when we need to inform the incremental marker. 3769 // Fall through when we need to inform the incremental marker.
3830 } 3770 }
3831 3771
3832
3833 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 3772 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
3834 CEntryStub ces(isolate(), 1, kSaveFPRegs); 3773 CEntryStub ces(isolate(), 1, kSaveFPRegs);
3835 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); 3774 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
3836 int parameter_count_offset = 3775 int parameter_count_offset =
3837 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 3776 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
3838 __ LoadP(r4, MemOperand(fp, parameter_count_offset)); 3777 __ LoadP(r3, MemOperand(fp, parameter_count_offset));
3839 if (function_mode() == JS_FUNCTION_STUB_MODE) { 3778 if (function_mode() == JS_FUNCTION_STUB_MODE) {
3840 __ addi(r4, r4, Operand(1)); 3779 __ AddP(r3, Operand(1));
3841 } 3780 }
3842 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 3781 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
3843 __ slwi(r4, r4, Operand(kPointerSizeLog2)); 3782 __ ShiftLeftP(r3, r3, Operand(kPointerSizeLog2));
3844 __ add(sp, sp, r4); 3783 __ la(sp, MemOperand(r3, sp));
3845 __ Ret(); 3784 __ Ret();
3846 } 3785 }
3847 3786
3848
3849 void LoadICTrampolineStub::Generate(MacroAssembler* masm) { 3787 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
3850 __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister()); 3788 __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
3851 LoadICStub stub(isolate(), state()); 3789 LoadICStub stub(isolate(), state());
3852 stub.GenerateForTrampoline(masm); 3790 stub.GenerateForTrampoline(masm);
3853 } 3791 }
3854 3792
3855
3856 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { 3793 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
3857 __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister()); 3794 __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
3858 KeyedLoadICStub stub(isolate(), state()); 3795 KeyedLoadICStub stub(isolate(), state());
3859 stub.GenerateForTrampoline(masm); 3796 stub.GenerateForTrampoline(masm);
3860 } 3797 }
3861 3798
3862
3863 void CallICTrampolineStub::Generate(MacroAssembler* masm) { 3799 void CallICTrampolineStub::Generate(MacroAssembler* masm) {
3864 __ EmitLoadTypeFeedbackVector(r5); 3800 __ EmitLoadTypeFeedbackVector(r4);
3865 CallICStub stub(isolate(), state()); 3801 CallICStub stub(isolate(), state());
3866 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 3802 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
3867 } 3803 }
3868 3804
3869
3870 void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); } 3805 void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); }
3871 3806
3872
3873 void LoadICStub::GenerateForTrampoline(MacroAssembler* masm) { 3807 void LoadICStub::GenerateForTrampoline(MacroAssembler* masm) {
3874 GenerateImpl(masm, true); 3808 GenerateImpl(masm, true);
3875 } 3809 }
3876 3810
3877
3878 static void HandleArrayCases(MacroAssembler* masm, Register feedback, 3811 static void HandleArrayCases(MacroAssembler* masm, Register feedback,
3879 Register receiver_map, Register scratch1, 3812 Register receiver_map, Register scratch1,
3880 Register scratch2, bool is_polymorphic, 3813 Register scratch2, bool is_polymorphic,
3881 Label* miss) { 3814 Label* miss) {
3882 // feedback initially contains the feedback array 3815 // feedback initially contains the feedback array
3883 Label next_loop, prepare_next; 3816 Label next_loop, prepare_next;
3884 Label start_polymorphic; 3817 Label start_polymorphic;
3885 3818
3886 Register cached_map = scratch1; 3819 Register cached_map = scratch1;
3887 3820
3888 __ LoadP(cached_map, 3821 __ LoadP(cached_map,
3889 FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(0))); 3822 FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(0)));
3890 __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); 3823 __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset));
3891 __ cmp(receiver_map, cached_map); 3824 __ CmpP(receiver_map, cached_map);
3892 __ bne(&start_polymorphic); 3825 __ bne(&start_polymorphic, Label::kNear);
3893 // found, now call handler. 3826 // found, now call handler.
3894 Register handler = feedback; 3827 Register handler = feedback;
3895 __ LoadP(handler, 3828 __ LoadP(handler,
3896 FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(1))); 3829 FieldMemOperand(feedback, FixedArray::OffsetOfElementAt(1)));
3897 __ addi(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag)); 3830 __ AddP(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag));
3898 __ Jump(ip); 3831 __ Jump(ip);
3899 3832
3900
3901 Register length = scratch2; 3833 Register length = scratch2;
3902 __ bind(&start_polymorphic); 3834 __ bind(&start_polymorphic);
3903 __ LoadP(length, FieldMemOperand(feedback, FixedArray::kLengthOffset)); 3835 __ LoadP(length, FieldMemOperand(feedback, FixedArray::kLengthOffset));
3904 if (!is_polymorphic) { 3836 if (!is_polymorphic) {
3905 // If the IC could be monomorphic we have to make sure we don't go past the 3837 // If the IC could be monomorphic we have to make sure we don't go past the
3906 // end of the feedback array. 3838 // end of the feedback array.
3907 __ CmpSmiLiteral(length, Smi::FromInt(2), r0); 3839 __ CmpSmiLiteral(length, Smi::FromInt(2), r0);
3908 __ beq(miss); 3840 __ beq(miss);
3909 } 3841 }
3910 3842
3911 Register too_far = length; 3843 Register too_far = length;
3912 Register pointer_reg = feedback; 3844 Register pointer_reg = feedback;
3913 3845
3914 // +-----+------+------+-----+-----+ ... ----+ 3846 // +-----+------+------+-----+-----+ ... ----+
3915 // | map | len | wm0 | h0 | wm1 | hN | 3847 // | map | len | wm0 | h0 | wm1 | hN |
3916 // +-----+------+------+-----+-----+ ... ----+ 3848 // +-----+------+------+-----+-----+ ... ----+
3917 // 0 1 2 len-1 3849 // 0 1 2 len-1
3918 // ^ ^ 3850 // ^ ^
3919 // | | 3851 // | |
3920 // pointer_reg too_far 3852 // pointer_reg too_far
3921 // aka feedback scratch2 3853 // aka feedback scratch2
3922 // also need receiver_map 3854 // also need receiver_map
3923 // use cached_map (scratch1) to look in the weak map values. 3855 // use cached_map (scratch1) to look in the weak map values.
3924 __ SmiToPtrArrayOffset(r0, length); 3856 __ SmiToPtrArrayOffset(r0, length);
3925 __ add(too_far, feedback, r0); 3857 __ AddP(too_far, feedback, r0);
3926 __ addi(too_far, too_far, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3858 __ AddP(too_far, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3927 __ addi(pointer_reg, feedback, 3859 __ AddP(pointer_reg, feedback,
3928 Operand(FixedArray::OffsetOfElementAt(2) - kHeapObjectTag)); 3860 Operand(FixedArray::OffsetOfElementAt(2) - kHeapObjectTag));
3929 3861
3930 __ bind(&next_loop); 3862 __ bind(&next_loop);
3931 __ LoadP(cached_map, MemOperand(pointer_reg)); 3863 __ LoadP(cached_map, MemOperand(pointer_reg));
3932 __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); 3864 __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset));
3933 __ cmp(receiver_map, cached_map); 3865 __ CmpP(receiver_map, cached_map);
3934 __ bne(&prepare_next); 3866 __ bne(&prepare_next, Label::kNear);
3935 __ LoadP(handler, MemOperand(pointer_reg, kPointerSize)); 3867 __ LoadP(handler, MemOperand(pointer_reg, kPointerSize));
3936 __ addi(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag)); 3868 __ AddP(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag));
3937 __ Jump(ip); 3869 __ Jump(ip);
3938 3870
3939 __ bind(&prepare_next); 3871 __ bind(&prepare_next);
3940 __ addi(pointer_reg, pointer_reg, Operand(kPointerSize * 2)); 3872 __ AddP(pointer_reg, Operand(kPointerSize * 2));
3941 __ cmp(pointer_reg, too_far); 3873 __ CmpP(pointer_reg, too_far);
3942 __ blt(&next_loop); 3874 __ blt(&next_loop, Label::kNear);
3943 3875
3944 // We exhausted our array of map handler pairs. 3876 // We exhausted our array of map handler pairs.
3945 __ b(miss); 3877 __ b(miss);
3946 } 3878 }
3947 3879
3948
3949 static void HandleMonomorphicCase(MacroAssembler* masm, Register receiver, 3880 static void HandleMonomorphicCase(MacroAssembler* masm, Register receiver,
3950 Register receiver_map, Register feedback, 3881 Register receiver_map, Register feedback,
3951 Register vector, Register slot, 3882 Register vector, Register slot,
3952 Register scratch, Label* compare_map, 3883 Register scratch, Label* compare_map,
3953 Label* load_smi_map, Label* try_array) { 3884 Label* load_smi_map, Label* try_array) {
3954 __ JumpIfSmi(receiver, load_smi_map); 3885 __ JumpIfSmi(receiver, load_smi_map);
3955 __ LoadP(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 3886 __ LoadP(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
3956 __ bind(compare_map); 3887 __ bind(compare_map);
3957 Register cached_map = scratch; 3888 Register cached_map = scratch;
3958 // Move the weak map into the weak_cell register. 3889 // Move the weak map into the weak_cell register.
3959 __ LoadP(cached_map, FieldMemOperand(feedback, WeakCell::kValueOffset)); 3890 __ LoadP(cached_map, FieldMemOperand(feedback, WeakCell::kValueOffset));
3960 __ cmp(cached_map, receiver_map); 3891 __ CmpP(cached_map, receiver_map);
3961 __ bne(try_array); 3892 __ bne(try_array);
3962 Register handler = feedback; 3893 Register handler = feedback;
3963 __ SmiToPtrArrayOffset(r0, slot); 3894 __ SmiToPtrArrayOffset(r1, slot);
3964 __ add(handler, vector, r0);
3965 __ LoadP(handler, 3895 __ LoadP(handler,
3966 FieldMemOperand(handler, FixedArray::kHeaderSize + kPointerSize)); 3896 FieldMemOperand(r1, vector, FixedArray::kHeaderSize + kPointerSize));
3967 __ addi(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag)); 3897 __ AddP(ip, handler, Operand(Code::kHeaderSize - kHeapObjectTag));
3968 __ Jump(ip); 3898 __ Jump(ip);
3969 } 3899 }
3970 3900
3901 void LoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
3902 Register receiver = LoadWithVectorDescriptor::ReceiverRegister(); // r3
3903 Register name = LoadWithVectorDescriptor::NameRegister(); // r4
3904 Register vector = LoadWithVectorDescriptor::VectorRegister(); // r5
3905 Register slot = LoadWithVectorDescriptor::SlotRegister(); // r2
3906 Register feedback = r6;
3907 Register receiver_map = r7;
3908 Register scratch1 = r8;
3971 3909
3972 void LoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 3910 __ SmiToPtrArrayOffset(r1, slot);
3973 Register receiver = LoadWithVectorDescriptor::ReceiverRegister(); // r4 3911 __ LoadP(feedback, FieldMemOperand(r1, vector, FixedArray::kHeaderSize));
3974 Register name = LoadWithVectorDescriptor::NameRegister(); // r5
3975 Register vector = LoadWithVectorDescriptor::VectorRegister(); // r6
3976 Register slot = LoadWithVectorDescriptor::SlotRegister(); // r3
3977 Register feedback = r7;
3978 Register receiver_map = r8;
3979 Register scratch1 = r9;
3980
3981 __ SmiToPtrArrayOffset(r0, slot);
3982 __ add(feedback, vector, r0);
3983 __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize));
3984 3912
3985 // Try to quickly handle the monomorphic case without knowing for sure 3913 // Try to quickly handle the monomorphic case without knowing for sure
3986 // if we have a weak cell in feedback. We do know it's safe to look 3914 // if we have a weak cell in feedback. We do know it's safe to look
3987 // at WeakCell::kValueOffset. 3915 // at WeakCell::kValueOffset.
3988 Label try_array, load_smi_map, compare_map; 3916 Label try_array, load_smi_map, compare_map;
3989 Label not_array, miss; 3917 Label not_array, miss;
3990 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 3918 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot,
3991 scratch1, &compare_map, &load_smi_map, &try_array); 3919 scratch1, &compare_map, &load_smi_map, &try_array);
3992 3920
3993 // Is it a fixed array? 3921 // Is it a fixed array?
3994 __ bind(&try_array); 3922 __ bind(&try_array);
3995 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 3923 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset));
3996 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 3924 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex);
3997 __ bne(&not_array); 3925 __ bne(&not_array, Label::kNear);
3998 HandleArrayCases(masm, feedback, receiver_map, scratch1, r10, true, &miss); 3926 HandleArrayCases(masm, feedback, receiver_map, scratch1, r9, true, &miss);
3999 3927
4000 __ bind(&not_array); 3928 __ bind(&not_array);
4001 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 3929 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
4002 __ bne(&miss); 3930 __ bne(&miss);
4003 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( 3931 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
4004 Code::ComputeHandlerFlags(Code::LOAD_IC)); 3932 Code::ComputeHandlerFlags(Code::LOAD_IC));
4005 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags, 3933 masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
4006 receiver, name, feedback, 3934 receiver, name, feedback,
4007 receiver_map, scratch1, r10); 3935 receiver_map, scratch1, r9);
4008 3936
4009 __ bind(&miss); 3937 __ bind(&miss);
4010 LoadIC::GenerateMiss(masm); 3938 LoadIC::GenerateMiss(masm);
4011 3939
4012 __ bind(&load_smi_map); 3940 __ bind(&load_smi_map);
4013 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 3941 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
4014 __ b(&compare_map); 3942 __ b(&compare_map);
4015 } 3943 }
4016 3944
4017
4018 void KeyedLoadICStub::Generate(MacroAssembler* masm) { 3945 void KeyedLoadICStub::Generate(MacroAssembler* masm) {
4019 GenerateImpl(masm, false); 3946 GenerateImpl(masm, false);
4020 } 3947 }
4021 3948
4022
4023 void KeyedLoadICStub::GenerateForTrampoline(MacroAssembler* masm) { 3949 void KeyedLoadICStub::GenerateForTrampoline(MacroAssembler* masm) {
4024 GenerateImpl(masm, true); 3950 GenerateImpl(masm, true);
4025 } 3951 }
4026 3952
3953 void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
3954 Register receiver = LoadWithVectorDescriptor::ReceiverRegister(); // r3
3955 Register key = LoadWithVectorDescriptor::NameRegister(); // r4
3956 Register vector = LoadWithVectorDescriptor::VectorRegister(); // r5
3957 Register slot = LoadWithVectorDescriptor::SlotRegister(); // r2
3958 Register feedback = r6;
3959 Register receiver_map = r7;
3960 Register scratch1 = r8;
4027 3961
4028 void KeyedLoadICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 3962 __ SmiToPtrArrayOffset(r1, slot);
4029 Register receiver = LoadWithVectorDescriptor::ReceiverRegister(); // r4 3963 __ LoadP(feedback, FieldMemOperand(r1, vector, FixedArray::kHeaderSize));
4030 Register key = LoadWithVectorDescriptor::NameRegister(); // r5
4031 Register vector = LoadWithVectorDescriptor::VectorRegister(); // r6
4032 Register slot = LoadWithVectorDescriptor::SlotRegister(); // r3
4033 Register feedback = r7;
4034 Register receiver_map = r8;
4035 Register scratch1 = r9;
4036
4037 __ SmiToPtrArrayOffset(r0, slot);
4038 __ add(feedback, vector, r0);
4039 __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize));
4040 3964
4041 // Try to quickly handle the monomorphic case without knowing for sure 3965 // Try to quickly handle the monomorphic case without knowing for sure
4042 // if we have a weak cell in feedback. We do know it's safe to look 3966 // if we have a weak cell in feedback. We do know it's safe to look
4043 // at WeakCell::kValueOffset. 3967 // at WeakCell::kValueOffset.
4044 Label try_array, load_smi_map, compare_map; 3968 Label try_array, load_smi_map, compare_map;
4045 Label not_array, miss; 3969 Label not_array, miss;
4046 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 3970 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot,
4047 scratch1, &compare_map, &load_smi_map, &try_array); 3971 scratch1, &compare_map, &load_smi_map, &try_array);
4048 3972
4049 __ bind(&try_array); 3973 __ bind(&try_array);
4050 // Is it a fixed array? 3974 // Is it a fixed array?
4051 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 3975 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset));
4052 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 3976 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex);
4053 __ bne(&not_array); 3977 __ bne(&not_array);
4054 3978
4055 // We have a polymorphic element handler. 3979 // We have a polymorphic element handler.
4056 Label polymorphic, try_poly_name; 3980 Label polymorphic, try_poly_name;
4057 __ bind(&polymorphic); 3981 __ bind(&polymorphic);
4058 HandleArrayCases(masm, feedback, receiver_map, scratch1, r10, true, &miss); 3982 HandleArrayCases(masm, feedback, receiver_map, scratch1, r9, true, &miss);
4059 3983
4060 __ bind(&not_array); 3984 __ bind(&not_array);
4061 // Is it generic? 3985 // Is it generic?
4062 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 3986 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
4063 __ bne(&try_poly_name); 3987 __ bne(&try_poly_name);
4064 Handle<Code> megamorphic_stub = 3988 Handle<Code> megamorphic_stub =
4065 KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); 3989 KeyedLoadIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
4066 __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET); 3990 __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
4067 3991
4068 __ bind(&try_poly_name); 3992 __ bind(&try_poly_name);
4069 // We might have a name in feedback, and a fixed array in the next slot. 3993 // We might have a name in feedback, and a fixed array in the next slot.
4070 __ cmp(key, feedback); 3994 __ CmpP(key, feedback);
4071 __ bne(&miss); 3995 __ bne(&miss);
4072 // If the name comparison succeeded, we know we have a fixed array with 3996 // If the name comparison succeeded, we know we have a fixed array with
4073 // at least one map/handler pair. 3997 // at least one map/handler pair.
4074 __ SmiToPtrArrayOffset(r0, slot); 3998 __ SmiToPtrArrayOffset(r1, slot);
4075 __ add(feedback, vector, r0);
4076 __ LoadP(feedback, 3999 __ LoadP(feedback,
4077 FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize)); 4000 FieldMemOperand(r1, vector, FixedArray::kHeaderSize + kPointerSize));
4078 HandleArrayCases(masm, feedback, receiver_map, scratch1, r10, false, &miss); 4001 HandleArrayCases(masm, feedback, receiver_map, scratch1, r9, false, &miss);
4079 4002
4080 __ bind(&miss); 4003 __ bind(&miss);
4081 KeyedLoadIC::GenerateMiss(masm); 4004 KeyedLoadIC::GenerateMiss(masm);
4082 4005
4083 __ bind(&load_smi_map); 4006 __ bind(&load_smi_map);
4084 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 4007 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
4085 __ b(&compare_map); 4008 __ b(&compare_map);
4086 } 4009 }
4087 4010
4088
4089 void VectorStoreICTrampolineStub::Generate(MacroAssembler* masm) { 4011 void VectorStoreICTrampolineStub::Generate(MacroAssembler* masm) {
4090 __ EmitLoadTypeFeedbackVector(VectorStoreICDescriptor::VectorRegister()); 4012 __ EmitLoadTypeFeedbackVector(VectorStoreICDescriptor::VectorRegister());
4091 VectorStoreICStub stub(isolate(), state()); 4013 VectorStoreICStub stub(isolate(), state());
4092 stub.GenerateForTrampoline(masm); 4014 stub.GenerateForTrampoline(masm);
4093 } 4015 }
4094 4016
4095
4096 void VectorKeyedStoreICTrampolineStub::Generate(MacroAssembler* masm) { 4017 void VectorKeyedStoreICTrampolineStub::Generate(MacroAssembler* masm) {
4097 __ EmitLoadTypeFeedbackVector(VectorStoreICDescriptor::VectorRegister()); 4018 __ EmitLoadTypeFeedbackVector(VectorStoreICDescriptor::VectorRegister());
4098 VectorKeyedStoreICStub stub(isolate(), state()); 4019 VectorKeyedStoreICStub stub(isolate(), state());
4099 stub.GenerateForTrampoline(masm); 4020 stub.GenerateForTrampoline(masm);
4100 } 4021 }
4101 4022
4102
4103 void VectorStoreICStub::Generate(MacroAssembler* masm) { 4023 void VectorStoreICStub::Generate(MacroAssembler* masm) {
4104 GenerateImpl(masm, false); 4024 GenerateImpl(masm, false);
4105 } 4025 }
4106 4026
4107
4108 void VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { 4027 void VectorStoreICStub::GenerateForTrampoline(MacroAssembler* masm) {
4109 GenerateImpl(masm, true); 4028 GenerateImpl(masm, true);
4110 } 4029 }
4111 4030
4112
4113 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 4031 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
4114 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // r4 4032 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // r3
4115 Register key = VectorStoreICDescriptor::NameRegister(); // r5 4033 Register key = VectorStoreICDescriptor::NameRegister(); // r4
4116 Register vector = VectorStoreICDescriptor::VectorRegister(); // r6 4034 Register vector = VectorStoreICDescriptor::VectorRegister(); // r5
4117 Register slot = VectorStoreICDescriptor::SlotRegister(); // r7 4035 Register slot = VectorStoreICDescriptor::SlotRegister(); // r6
4118 DCHECK(VectorStoreICDescriptor::ValueRegister().is(r3)); // r3 4036 DCHECK(VectorStoreICDescriptor::ValueRegister().is(r2)); // r2
4119 Register feedback = r8; 4037 Register feedback = r7;
4120 Register receiver_map = r9; 4038 Register receiver_map = r8;
4121 Register scratch1 = r10; 4039 Register scratch1 = r9;
4122 4040
4123 __ SmiToPtrArrayOffset(r0, slot); 4041 __ SmiToPtrArrayOffset(r0, slot);
4124 __ add(feedback, vector, r0); 4042 __ AddP(feedback, vector, r0);
4125 __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); 4043 __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize));
4126 4044
4127 // Try to quickly handle the monomorphic case without knowing for sure 4045 // Try to quickly handle the monomorphic case without knowing for sure
4128 // if we have a weak cell in feedback. We do know it's safe to look 4046 // if we have a weak cell in feedback. We do know it's safe to look
4129 // at WeakCell::kValueOffset. 4047 // at WeakCell::kValueOffset.
4130 Label try_array, load_smi_map, compare_map; 4048 Label try_array, load_smi_map, compare_map;
4131 Label not_array, miss; 4049 Label not_array, miss;
4132 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 4050 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot,
4133 scratch1, &compare_map, &load_smi_map, &try_array); 4051 scratch1, &compare_map, &load_smi_map, &try_array);
4134 4052
4135 // Is it a fixed array? 4053 // Is it a fixed array?
4136 __ bind(&try_array); 4054 __ bind(&try_array);
4137 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 4055 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset));
4138 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 4056 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex);
4139 __ bne(&not_array); 4057 __ bne(&not_array);
4140 4058
4141 Register scratch2 = r11; 4059 Register scratch2 = ip;
4142 HandleArrayCases(masm, feedback, receiver_map, scratch1, scratch2, true, 4060 HandleArrayCases(masm, feedback, receiver_map, scratch1, scratch2, true,
4143 &miss); 4061 &miss);
4144 4062
4145 __ bind(&not_array); 4063 __ bind(&not_array);
4146 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 4064 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
4147 __ bne(&miss); 4065 __ bne(&miss);
4148 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( 4066 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
4149 Code::ComputeHandlerFlags(Code::STORE_IC)); 4067 Code::ComputeHandlerFlags(Code::STORE_IC));
4150 masm->isolate()->stub_cache()->GenerateProbe( 4068 masm->isolate()->stub_cache()->GenerateProbe(
4151 masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map, 4069 masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map,
4152 scratch1, scratch2); 4070 scratch1, scratch2);
4153 4071
4154 __ bind(&miss); 4072 __ bind(&miss);
4155 StoreIC::GenerateMiss(masm); 4073 StoreIC::GenerateMiss(masm);
4156 4074
4157 __ bind(&load_smi_map); 4075 __ bind(&load_smi_map);
4158 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 4076 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
4159 __ b(&compare_map); 4077 __ b(&compare_map);
4160 } 4078 }
4161 4079
4162
4163 void VectorKeyedStoreICStub::Generate(MacroAssembler* masm) { 4080 void VectorKeyedStoreICStub::Generate(MacroAssembler* masm) {
4164 GenerateImpl(masm, false); 4081 GenerateImpl(masm, false);
4165 } 4082 }
4166 4083
4167
4168 void VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) { 4084 void VectorKeyedStoreICStub::GenerateForTrampoline(MacroAssembler* masm) {
4169 GenerateImpl(masm, true); 4085 GenerateImpl(masm, true);
4170 } 4086 }
4171 4087
4172
4173 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register feedback, 4088 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register feedback,
4174 Register receiver_map, Register scratch1, 4089 Register receiver_map, Register scratch1,
4175 Register scratch2, Label* miss) { 4090 Register scratch2, Label* miss) {
4176 // feedback initially contains the feedback array 4091 // feedback initially contains the feedback array
4177 Label next_loop, prepare_next; 4092 Label next_loop, prepare_next;
4178 Label start_polymorphic; 4093 Label start_polymorphic;
4179 Label transition_call; 4094 Label transition_call;
4180 4095
4181 Register cached_map = scratch1; 4096 Register cached_map = scratch1;
4182 Register too_far = scratch2; 4097 Register too_far = scratch2;
4183 Register pointer_reg = feedback; 4098 Register pointer_reg = feedback;
4184 __ LoadP(too_far, FieldMemOperand(feedback, FixedArray::kLengthOffset)); 4099 __ LoadP(too_far, FieldMemOperand(feedback, FixedArray::kLengthOffset));
4185 4100
4186 // +-----+------+------+-----+-----+-----+ ... ----+ 4101 // +-----+------+------+-----+-----+-----+ ... ----+
4187 // | map | len | wm0 | wt0 | h0 | wm1 | hN | 4102 // | map | len | wm0 | wt0 | h0 | wm1 | hN |
4188 // +-----+------+------+-----+-----+ ----+ ... ----+ 4103 // +-----+------+------+-----+-----+ ----+ ... ----+
4189 // 0 1 2 len-1 4104 // 0 1 2 len-1
4190 // ^ ^ 4105 // ^ ^
4191 // | | 4106 // | |
4192 // pointer_reg too_far 4107 // pointer_reg too_far
4193 // aka feedback scratch2 4108 // aka feedback scratch2
4194 // also need receiver_map 4109 // also need receiver_map
4195 // use cached_map (scratch1) to look in the weak map values. 4110 // use cached_map (scratch1) to look in the weak map values.
4196 __ SmiToPtrArrayOffset(r0, too_far); 4111 __ SmiToPtrArrayOffset(r0, too_far);
4197 __ add(too_far, feedback, r0); 4112 __ AddP(too_far, feedback, r0);
4198 __ addi(too_far, too_far, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4113 __ AddP(too_far, too_far, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4199 __ addi(pointer_reg, feedback, 4114 __ AddP(pointer_reg, feedback,
4200 Operand(FixedArray::OffsetOfElementAt(0) - kHeapObjectTag)); 4115 Operand(FixedArray::OffsetOfElementAt(0) - kHeapObjectTag));
4201 4116
4202 __ bind(&next_loop); 4117 __ bind(&next_loop);
4203 __ LoadP(cached_map, MemOperand(pointer_reg)); 4118 __ LoadP(cached_map, MemOperand(pointer_reg));
4204 __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset)); 4119 __ LoadP(cached_map, FieldMemOperand(cached_map, WeakCell::kValueOffset));
4205 __ cmp(receiver_map, cached_map); 4120 __ CmpP(receiver_map, cached_map);
4206 __ bne(&prepare_next); 4121 __ bne(&prepare_next);
4207 // Is it a transitioning store? 4122 // Is it a transitioning store?
4208 __ LoadP(too_far, MemOperand(pointer_reg, kPointerSize)); 4123 __ LoadP(too_far, MemOperand(pointer_reg, kPointerSize));
4209 __ CompareRoot(too_far, Heap::kUndefinedValueRootIndex); 4124 __ CompareRoot(too_far, Heap::kUndefinedValueRootIndex);
4210 __ bne(&transition_call); 4125 __ bne(&transition_call);
4211 __ LoadP(pointer_reg, MemOperand(pointer_reg, kPointerSize * 2)); 4126 __ LoadP(pointer_reg, MemOperand(pointer_reg, kPointerSize * 2));
4212 __ addi(ip, pointer_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); 4127 __ AddP(ip, pointer_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
4213 __ Jump(ip); 4128 __ Jump(ip);
4214 4129
4215 __ bind(&transition_call); 4130 __ bind(&transition_call);
4216 __ LoadP(too_far, FieldMemOperand(too_far, WeakCell::kValueOffset)); 4131 __ LoadP(too_far, FieldMemOperand(too_far, WeakCell::kValueOffset));
4217 __ JumpIfSmi(too_far, miss); 4132 __ JumpIfSmi(too_far, miss);
4218 4133
4219 __ LoadP(receiver_map, MemOperand(pointer_reg, kPointerSize * 2)); 4134 __ LoadP(receiver_map, MemOperand(pointer_reg, kPointerSize * 2));
4220 4135
4221 // Load the map into the correct register. 4136 // Load the map into the correct register.
4222 DCHECK(feedback.is(VectorStoreTransitionDescriptor::MapRegister())); 4137 DCHECK(feedback.is(VectorStoreTransitionDescriptor::MapRegister()));
4223 __ mr(feedback, too_far); 4138 __ LoadRR(feedback, too_far);
4224 4139
4225 __ addi(ip, receiver_map, Operand(Code::kHeaderSize - kHeapObjectTag)); 4140 __ AddP(ip, receiver_map, Operand(Code::kHeaderSize - kHeapObjectTag));
4226 __ Jump(ip); 4141 __ Jump(ip);
4227 4142
4228 __ bind(&prepare_next); 4143 __ bind(&prepare_next);
4229 __ addi(pointer_reg, pointer_reg, Operand(kPointerSize * 3)); 4144 __ AddP(pointer_reg, pointer_reg, Operand(kPointerSize * 3));
4230 __ cmpl(pointer_reg, too_far); 4145 __ CmpLogicalP(pointer_reg, too_far);
4231 __ blt(&next_loop); 4146 __ blt(&next_loop);
4232 4147
4233 // We exhausted our array of map handler pairs. 4148 // We exhausted our array of map handler pairs.
4234 __ b(miss); 4149 __ b(miss);
4235 } 4150 }
4236 4151
4237
4238 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { 4152 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) {
4239 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // r4 4153 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // r3
4240 Register key = VectorStoreICDescriptor::NameRegister(); // r5 4154 Register key = VectorStoreICDescriptor::NameRegister(); // r4
4241 Register vector = VectorStoreICDescriptor::VectorRegister(); // r6 4155 Register vector = VectorStoreICDescriptor::VectorRegister(); // r5
4242 Register slot = VectorStoreICDescriptor::SlotRegister(); // r7 4156 Register slot = VectorStoreICDescriptor::SlotRegister(); // r6
4243 DCHECK(VectorStoreICDescriptor::ValueRegister().is(r3)); // r3 4157 DCHECK(VectorStoreICDescriptor::ValueRegister().is(r2)); // r2
4244 Register feedback = r8; 4158 Register feedback = r7;
4245 Register receiver_map = r9; 4159 Register receiver_map = r8;
4246 Register scratch1 = r10; 4160 Register scratch1 = r9;
4247 4161
4248 __ SmiToPtrArrayOffset(r0, slot); 4162 __ SmiToPtrArrayOffset(r0, slot);
4249 __ add(feedback, vector, r0); 4163 __ AddP(feedback, vector, r0);
4250 __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); 4164 __ LoadP(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize));
4251 4165
4252 // Try to quickly handle the monomorphic case without knowing for sure 4166 // Try to quickly handle the monomorphic case without knowing for sure
4253 // if we have a weak cell in feedback. We do know it's safe to look 4167 // if we have a weak cell in feedback. We do know it's safe to look
4254 // at WeakCell::kValueOffset. 4168 // at WeakCell::kValueOffset.
4255 Label try_array, load_smi_map, compare_map; 4169 Label try_array, load_smi_map, compare_map;
4256 Label not_array, miss; 4170 Label not_array, miss;
4257 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot, 4171 HandleMonomorphicCase(masm, receiver, receiver_map, feedback, vector, slot,
4258 scratch1, &compare_map, &load_smi_map, &try_array); 4172 scratch1, &compare_map, &load_smi_map, &try_array);
4259 4173
4260 __ bind(&try_array); 4174 __ bind(&try_array);
4261 // Is it a fixed array? 4175 // Is it a fixed array?
4262 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset)); 4176 __ LoadP(scratch1, FieldMemOperand(feedback, HeapObject::kMapOffset));
4263 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex); 4177 __ CompareRoot(scratch1, Heap::kFixedArrayMapRootIndex);
4264 __ bne(&not_array); 4178 __ bne(&not_array);
4265 4179
4266 // We have a polymorphic element handler. 4180 // We have a polymorphic element handler.
4267 Label polymorphic, try_poly_name; 4181 Label polymorphic, try_poly_name;
4268 __ bind(&polymorphic); 4182 __ bind(&polymorphic);
4269 4183
4270 Register scratch2 = r11; 4184 Register scratch2 = ip;
4271 4185
4272 HandlePolymorphicStoreCase(masm, feedback, receiver_map, scratch1, scratch2, 4186 HandlePolymorphicStoreCase(masm, feedback, receiver_map, scratch1, scratch2,
4273 &miss); 4187 &miss);
4274 4188
4275 __ bind(&not_array); 4189 __ bind(&not_array);
4276 // Is it generic? 4190 // Is it generic?
4277 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); 4191 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
4278 __ bne(&try_poly_name); 4192 __ bne(&try_poly_name);
4279 Handle<Code> megamorphic_stub = 4193 Handle<Code> megamorphic_stub =
4280 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState()); 4194 KeyedStoreIC::ChooseMegamorphicStub(masm->isolate(), GetExtraICState());
4281 __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET); 4195 __ Jump(megamorphic_stub, RelocInfo::CODE_TARGET);
4282 4196
4283 __ bind(&try_poly_name); 4197 __ bind(&try_poly_name);
4284 // We might have a name in feedback, and a fixed array in the next slot. 4198 // We might have a name in feedback, and a fixed array in the next slot.
4285 __ cmp(key, feedback); 4199 __ CmpP(key, feedback);
4286 __ bne(&miss); 4200 __ bne(&miss);
4287 // If the name comparison succeeded, we know we have a fixed array with 4201 // If the name comparison succeeded, we know we have a fixed array with
4288 // at least one map/handler pair. 4202 // at least one map/handler pair.
4289 __ SmiToPtrArrayOffset(r0, slot); 4203 __ SmiToPtrArrayOffset(r0, slot);
4290 __ add(feedback, vector, r0); 4204 __ AddP(feedback, vector, r0);
4291 __ LoadP(feedback, 4205 __ LoadP(feedback,
4292 FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize)); 4206 FieldMemOperand(feedback, FixedArray::kHeaderSize + kPointerSize));
4293 HandleArrayCases(masm, feedback, receiver_map, scratch1, scratch2, false, 4207 HandleArrayCases(masm, feedback, receiver_map, scratch1, scratch2, false,
4294 &miss); 4208 &miss);
4295 4209
4296 __ bind(&miss); 4210 __ bind(&miss);
4297 KeyedStoreIC::GenerateMiss(masm); 4211 KeyedStoreIC::GenerateMiss(masm);
4298 4212
4299 __ bind(&load_smi_map); 4213 __ bind(&load_smi_map);
4300 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); 4214 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex);
4301 __ b(&compare_map); 4215 __ b(&compare_map);
4302 } 4216 }
4303 4217
4304
4305 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 4218 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
4306 if (masm->isolate()->function_entry_hook() != NULL) { 4219 if (masm->isolate()->function_entry_hook() != NULL) {
4307 PredictableCodeSizeScope predictable(masm, 4220 PredictableCodeSizeScope predictable(masm,
4308 #if V8_TARGET_ARCH_PPC64 4221 #if V8_TARGET_ARCH_S390X
4309 14 * Assembler::kInstrSize); 4222 40);
4223 #elif V8_HOST_ARCH_S390
4224 36);
4310 #else 4225 #else
4311 11 * Assembler::kInstrSize); 4226 32);
4312 #endif 4227 #endif
4313 ProfileEntryHookStub stub(masm->isolate()); 4228 ProfileEntryHookStub stub(masm->isolate());
4314 __ mflr(r0); 4229 __ CleanseP(r14);
4315 __ Push(r0, ip); 4230 __ Push(r14, ip);
4316 __ CallStub(&stub); 4231 __ CallStub(&stub); // BRASL
4317 __ Pop(r0, ip); 4232 __ Pop(r14, ip);
4318 __ mtlr(r0);
4319 } 4233 }
4320 } 4234 }
4321 4235
4322
4323 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { 4236 void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
4324 // The entry hook is a "push lr, ip" instruction, followed by a call. 4237 // The entry hook is a "push lr" instruction (LAY+ST/STG), followed by a call.
4238 #if V8_TARGET_ARCH_S390X
4325 const int32_t kReturnAddressDistanceFromFunctionStart = 4239 const int32_t kReturnAddressDistanceFromFunctionStart =
4326 Assembler::kCallTargetAddressOffset + 3 * Assembler::kInstrSize; 4240 Assembler::kCallTargetAddressOffset + 18; // LAY + STG * 2
4241 #elif V8_HOST_ARCH_S390
4242 const int32_t kReturnAddressDistanceFromFunctionStart =
4243 Assembler::kCallTargetAddressOffset + 18; // NILH + LAY + ST * 2
4244 #else
4245 const int32_t kReturnAddressDistanceFromFunctionStart =
4246 Assembler::kCallTargetAddressOffset + 14; // LAY + ST * 2
4247 #endif
4327 4248
4328 // This should contain all kJSCallerSaved registers. 4249 // This should contain all kJSCallerSaved registers.
4329 const RegList kSavedRegs = kJSCallerSaved | // Caller saved registers. 4250 const RegList kSavedRegs = kJSCallerSaved | // Caller saved registers.
4330 r15.bit(); // Saved stack pointer. 4251 r7.bit(); // Saved stack pointer.
4331 4252
4332 // We also save lr, so the count here is one higher than the mask indicates. 4253 // We also save r14+ip, so count here is one higher than the mask indicates.
4333 const int32_t kNumSavedRegs = kNumJSCallerSaved + 2; 4254 const int32_t kNumSavedRegs = kNumJSCallerSaved + 3;
4334 4255
4335 // Save all caller-save registers as this may be called from anywhere. 4256 // Save all caller-save registers as this may be called from anywhere.
4336 __ mflr(ip); 4257 __ CleanseP(r14);
4258 __ LoadRR(ip, r14);
4337 __ MultiPush(kSavedRegs | ip.bit()); 4259 __ MultiPush(kSavedRegs | ip.bit());
4338 4260
4339 // Compute the function's address for the first argument. 4261 // Compute the function's address for the first argument.
4340 __ subi(r3, ip, Operand(kReturnAddressDistanceFromFunctionStart)); 4262
4263 __ SubP(r2, ip, Operand(kReturnAddressDistanceFromFunctionStart));
4341 4264
4342 // The caller's return address is two slots above the saved temporaries. 4265 // The caller's return address is two slots above the saved temporaries.
4343 // Grab that for the second argument to the hook. 4266 // Grab that for the second argument to the hook.
4344 __ addi(r4, sp, Operand((kNumSavedRegs + 1) * kPointerSize)); 4267 __ lay(r3, MemOperand(sp, kNumSavedRegs * kPointerSize));
4345 4268
4346 // Align the stack if necessary. 4269 // Align the stack if necessary.
4347 int frame_alignment = masm->ActivationFrameAlignment(); 4270 int frame_alignment = masm->ActivationFrameAlignment();
4348 if (frame_alignment > kPointerSize) { 4271 if (frame_alignment > kPointerSize) {
4349 __ mr(r15, sp); 4272 __ LoadRR(r7, sp);
4350 DCHECK(base::bits::IsPowerOfTwo32(frame_alignment)); 4273 DCHECK(base::bits::IsPowerOfTwo32(frame_alignment));
4351 __ ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment))); 4274 __ ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
4352 } 4275 }
4353 4276
4354 #if !defined(USE_SIMULATOR) 4277 #if !defined(USE_SIMULATOR)
4355 uintptr_t entry_hook = 4278 uintptr_t entry_hook =
4356 reinterpret_cast<uintptr_t>(isolate()->function_entry_hook()); 4279 reinterpret_cast<uintptr_t>(isolate()->function_entry_hook());
4357 #else 4280 __ mov(ip, Operand(entry_hook));
4281
4282 #if ABI_USES_FUNCTION_DESCRIPTORS
4283 // Function descriptor
4284 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize));
4285 __ LoadP(ip, MemOperand(ip, 0));
4286 // ip already set.
4287 #endif
4288 #endif
4289
4290 // zLinux ABI requires caller's frame to have sufficient space for callee
4291 // preserved regsiter save area.
4292 __ LoadImmP(r0, Operand::Zero());
4293 __ StoreP(r0, MemOperand(sp, -kCalleeRegisterSaveAreaSize -
4294 kNumRequiredStackFrameSlots * kPointerSize));
4295 __ lay(sp, MemOperand(sp, -kCalleeRegisterSaveAreaSize -
4296 kNumRequiredStackFrameSlots * kPointerSize));
4297 #if defined(USE_SIMULATOR)
4358 // Under the simulator we need to indirect the entry hook through a 4298 // Under the simulator we need to indirect the entry hook through a
4359 // trampoline function at a known address. 4299 // trampoline function at a known address.
4300 // It additionally takes an isolate as a third parameter
4301 __ mov(r4, Operand(ExternalReference::isolate_address(isolate())));
4302
4360 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); 4303 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
4361 ExternalReference entry_hook = ExternalReference( 4304 __ mov(ip, Operand(ExternalReference(
4362 &dispatcher, ExternalReference::BUILTIN_CALL, isolate()); 4305 &dispatcher, ExternalReference::BUILTIN_CALL, isolate())));
4363
4364 // It additionally takes an isolate as a third parameter
4365 __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
4366 #endif 4306 #endif
4367
4368 __ mov(ip, Operand(entry_hook));
4369
4370 if (ABI_USES_FUNCTION_DESCRIPTORS) {
4371 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize));
4372 __ LoadP(ip, MemOperand(ip, 0));
4373 }
4374 // ip set above, so nothing more to do for ABI_CALL_VIA_IP.
4375
4376 // PPC LINUX ABI:
4377 __ li(r0, Operand::Zero());
4378 __ StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize));
4379
4380 __ Call(ip); 4307 __ Call(ip);
4381 4308
4382 __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize)); 4309 // zLinux ABI requires caller's frame to have sufficient space for callee
4310 // preserved regsiter save area.
4311 __ la(sp, MemOperand(sp, kCalleeRegisterSaveAreaSize +
4312 kNumRequiredStackFrameSlots * kPointerSize));
4383 4313
4384 // Restore the stack pointer if needed. 4314 // Restore the stack pointer if needed.
4385 if (frame_alignment > kPointerSize) { 4315 if (frame_alignment > kPointerSize) {
4386 __ mr(sp, r15); 4316 __ LoadRR(sp, r7);
4387 } 4317 }
4388 4318
4389 // Also pop lr to get Ret(0). 4319 // Also pop lr to get Ret(0).
4390 __ MultiPop(kSavedRegs | ip.bit()); 4320 __ MultiPop(kSavedRegs | ip.bit());
4391 __ mtlr(ip); 4321 __ LoadRR(r14, ip);
4392 __ Ret(); 4322 __ Ret();
4393 } 4323 }
4394 4324
4395
4396 template <class T> 4325 template <class T>
4397 static void CreateArrayDispatch(MacroAssembler* masm, 4326 static void CreateArrayDispatch(MacroAssembler* masm,
4398 AllocationSiteOverrideMode mode) { 4327 AllocationSiteOverrideMode mode) {
4399 if (mode == DISABLE_ALLOCATION_SITES) { 4328 if (mode == DISABLE_ALLOCATION_SITES) {
4400 T stub(masm->isolate(), GetInitialFastElementsKind(), mode); 4329 T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
4401 __ TailCallStub(&stub); 4330 __ TailCallStub(&stub);
4402 } else if (mode == DONT_OVERRIDE) { 4331 } else if (mode == DONT_OVERRIDE) {
4403 int last_index = 4332 int last_index =
4404 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 4333 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
4405 for (int i = 0; i <= last_index; ++i) { 4334 for (int i = 0; i <= last_index; ++i) {
4406 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4335 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4407 __ Cmpi(r6, Operand(kind), r0); 4336 __ CmpP(r5, Operand(kind));
4408 T stub(masm->isolate(), kind); 4337 T stub(masm->isolate(), kind);
4409 __ TailCallStub(&stub, eq); 4338 __ TailCallStub(&stub, eq);
4410 } 4339 }
4411 4340
4412 // If we reached this point there is a problem. 4341 // If we reached this point there is a problem.
4413 __ Abort(kUnexpectedElementsKindInArrayConstructor); 4342 __ Abort(kUnexpectedElementsKindInArrayConstructor);
4414 } else { 4343 } else {
4415 UNREACHABLE(); 4344 UNREACHABLE();
4416 } 4345 }
4417 } 4346 }
4418 4347
4419
4420 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, 4348 static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
4421 AllocationSiteOverrideMode mode) { 4349 AllocationSiteOverrideMode mode) {
4422 // r5 - allocation site (if mode != DISABLE_ALLOCATION_SITES) 4350 // r4 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
4423 // r6 - kind (if mode != DISABLE_ALLOCATION_SITES) 4351 // r5 - kind (if mode != DISABLE_ALLOCATION_SITES)
4424 // r3 - number of arguments 4352 // r2 - number of arguments
4425 // r4 - constructor? 4353 // r3 - constructor?
4426 // sp[0] - last argument 4354 // sp[0] - last argument
4427 Label normal_sequence; 4355 Label normal_sequence;
4428 if (mode == DONT_OVERRIDE) { 4356 if (mode == DONT_OVERRIDE) {
4429 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); 4357 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
4430 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 4358 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
4431 STATIC_ASSERT(FAST_ELEMENTS == 2); 4359 STATIC_ASSERT(FAST_ELEMENTS == 2);
4432 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); 4360 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3);
4433 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4); 4361 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS == 4);
4434 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 4362 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
4435 4363
4436 // is the low bit set? If so, we are holey and that is good. 4364 // is the low bit set? If so, we are holey and that is good.
4437 __ andi(r0, r6, Operand(1)); 4365 __ AndP(r0, r5, Operand(1));
4438 __ bne(&normal_sequence, cr0); 4366 __ bne(&normal_sequence);
4439 } 4367 }
4440 4368
4441 // look at the first argument 4369 // look at the first argument
4442 __ LoadP(r8, MemOperand(sp, 0)); 4370 __ LoadP(r7, MemOperand(sp, 0));
4443 __ cmpi(r8, Operand::Zero()); 4371 __ CmpP(r7, Operand::Zero());
4444 __ beq(&normal_sequence); 4372 __ beq(&normal_sequence);
4445 4373
4446 if (mode == DISABLE_ALLOCATION_SITES) { 4374 if (mode == DISABLE_ALLOCATION_SITES) {
4447 ElementsKind initial = GetInitialFastElementsKind(); 4375 ElementsKind initial = GetInitialFastElementsKind();
4448 ElementsKind holey_initial = GetHoleyElementsKind(initial); 4376 ElementsKind holey_initial = GetHoleyElementsKind(initial);
4449 4377
4450 ArraySingleArgumentConstructorStub stub_holey( 4378 ArraySingleArgumentConstructorStub stub_holey(
4451 masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES); 4379 masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES);
4452 __ TailCallStub(&stub_holey); 4380 __ TailCallStub(&stub_holey);
4453 4381
4454 __ bind(&normal_sequence); 4382 __ bind(&normal_sequence);
4455 ArraySingleArgumentConstructorStub stub(masm->isolate(), initial, 4383 ArraySingleArgumentConstructorStub stub(masm->isolate(), initial,
4456 DISABLE_ALLOCATION_SITES); 4384 DISABLE_ALLOCATION_SITES);
4457 __ TailCallStub(&stub); 4385 __ TailCallStub(&stub);
4458 } else if (mode == DONT_OVERRIDE) { 4386 } else if (mode == DONT_OVERRIDE) {
4459 // We are going to create a holey array, but our kind is non-holey. 4387 // We are going to create a holey array, but our kind is non-holey.
4460 // Fix kind and retry (only if we have an allocation site in the slot). 4388 // Fix kind and retry (only if we have an allocation site in the slot).
4461 __ addi(r6, r6, Operand(1)); 4389 __ AddP(r5, r5, Operand(1));
4462
4463 if (FLAG_debug_code) { 4390 if (FLAG_debug_code) {
4464 __ LoadP(r8, FieldMemOperand(r5, 0)); 4391 __ LoadP(r7, FieldMemOperand(r4, 0));
4465 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex); 4392 __ CompareRoot(r7, Heap::kAllocationSiteMapRootIndex);
4466 __ Assert(eq, kExpectedAllocationSite); 4393 __ Assert(eq, kExpectedAllocationSite);
4467 } 4394 }
4468 4395
4469 // Save the resulting elements kind in type info. We can't just store r6 4396 // Save the resulting elements kind in type info. We can't just store r5
4470 // in the AllocationSite::transition_info field because elements kind is 4397 // in the AllocationSite::transition_info field because elements kind is
4471 // restricted to a portion of the field...upper bits need to be left alone. 4398 // restricted to a portion of the field...upper bits need to be left alone.
4472 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4399 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4473 __ LoadP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); 4400 __ LoadP(r6, FieldMemOperand(r4, AllocationSite::kTransitionInfoOffset));
4474 __ AddSmiLiteral(r7, r7, Smi::FromInt(kFastElementsKindPackedToHoley), r0); 4401 __ AddSmiLiteral(r6, r6, Smi::FromInt(kFastElementsKindPackedToHoley), r0);
4475 __ StoreP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset), 4402 __ StoreP(r6, FieldMemOperand(r4, AllocationSite::kTransitionInfoOffset));
4476 r0);
4477 4403
4478 __ bind(&normal_sequence); 4404 __ bind(&normal_sequence);
4479 int last_index = 4405 int last_index =
4480 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 4406 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
4481 for (int i = 0; i <= last_index; ++i) { 4407 for (int i = 0; i <= last_index; ++i) {
4482 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4408 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4483 __ mov(r0, Operand(kind)); 4409 __ CmpP(r5, Operand(kind));
4484 __ cmp(r6, r0);
4485 ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 4410 ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
4486 __ TailCallStub(&stub, eq); 4411 __ TailCallStub(&stub, eq);
4487 } 4412 }
4488 4413
4489 // If we reached this point there is a problem. 4414 // If we reached this point there is a problem.
4490 __ Abort(kUnexpectedElementsKindInArrayConstructor); 4415 __ Abort(kUnexpectedElementsKindInArrayConstructor);
4491 } else { 4416 } else {
4492 UNREACHABLE(); 4417 UNREACHABLE();
4493 } 4418 }
4494 } 4419 }
4495 4420
4496
4497 template <class T> 4421 template <class T>
4498 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 4422 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
4499 int to_index = 4423 int to_index =
4500 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); 4424 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
4501 for (int i = 0; i <= to_index; ++i) { 4425 for (int i = 0; i <= to_index; ++i) {
4502 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4426 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4503 T stub(isolate, kind); 4427 T stub(isolate, kind);
4504 stub.GetCode(); 4428 stub.GetCode();
4505 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 4429 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
4506 T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); 4430 T stub1(isolate, kind, DISABLE_ALLOCATION_SITES);
4507 stub1.GetCode(); 4431 stub1.GetCode();
4508 } 4432 }
4509 } 4433 }
4510 } 4434 }
4511 4435
4512
4513 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { 4436 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
4514 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 4437 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
4515 isolate); 4438 isolate);
4516 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 4439 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
4517 isolate); 4440 isolate);
4518 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( 4441 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
4519 isolate); 4442 isolate);
4520 } 4443 }
4521 4444
4522
4523 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( 4445 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
4524 Isolate* isolate) { 4446 Isolate* isolate) {
4525 ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS}; 4447 ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS};
4526 for (int i = 0; i < 2; i++) { 4448 for (int i = 0; i < 2; i++) {
4527 // For internal arrays we only need a few things 4449 // For internal arrays we only need a few things
4528 InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); 4450 InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]);
4529 stubh1.GetCode(); 4451 stubh1.GetCode();
4530 InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); 4452 InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
4531 stubh2.GetCode(); 4453 stubh2.GetCode();
4532 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); 4454 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
4533 stubh3.GetCode(); 4455 stubh3.GetCode();
4534 } 4456 }
4535 } 4457 }
4536 4458
4537
4538 void ArrayConstructorStub::GenerateDispatchToArrayStub( 4459 void ArrayConstructorStub::GenerateDispatchToArrayStub(
4539 MacroAssembler* masm, AllocationSiteOverrideMode mode) { 4460 MacroAssembler* masm, AllocationSiteOverrideMode mode) {
4540 if (argument_count() == ANY) { 4461 if (argument_count() == ANY) {
4541 Label not_zero_case, not_one_case; 4462 Label not_zero_case, not_one_case;
4542 __ cmpi(r3, Operand::Zero()); 4463 __ CmpP(r2, Operand::Zero());
4543 __ bne(&not_zero_case); 4464 __ bne(&not_zero_case);
4544 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4465 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4545 4466
4546 __ bind(&not_zero_case); 4467 __ bind(&not_zero_case);
4547 __ cmpi(r3, Operand(1)); 4468 __ CmpP(r2, Operand(1));
4548 __ bgt(&not_one_case); 4469 __ bgt(&not_one_case);
4549 CreateArrayDispatchOneArgument(masm, mode); 4470 CreateArrayDispatchOneArgument(masm, mode);
4550 4471
4551 __ bind(&not_one_case); 4472 __ bind(&not_one_case);
4552 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4473 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4553 } else if (argument_count() == NONE) { 4474 } else if (argument_count() == NONE) {
4554 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 4475 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4555 } else if (argument_count() == ONE) { 4476 } else if (argument_count() == ONE) {
4556 CreateArrayDispatchOneArgument(masm, mode); 4477 CreateArrayDispatchOneArgument(masm, mode);
4557 } else if (argument_count() == MORE_THAN_ONE) { 4478 } else if (argument_count() == MORE_THAN_ONE) {
4558 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 4479 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4559 } else { 4480 } else {
4560 UNREACHABLE(); 4481 UNREACHABLE();
4561 } 4482 }
4562 } 4483 }
4563 4484
4564
4565 void ArrayConstructorStub::Generate(MacroAssembler* masm) { 4485 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
4566 // ----------- S t a t e ------------- 4486 // ----------- S t a t e -------------
4567 // -- r3 : argc (only if argument_count() == ANY) 4487 // -- r2 : argc (only if argument_count() == ANY)
4568 // -- r4 : constructor 4488 // -- r3 : constructor
4569 // -- r5 : AllocationSite or undefined 4489 // -- r4 : AllocationSite or undefined
4570 // -- r6 : new target 4490 // -- r5 : new target
4571 // -- sp[0] : return address 4491 // -- sp[0] : return address
4572 // -- sp[4] : last argument 4492 // -- sp[4] : last argument
4573 // ----------------------------------- 4493 // -----------------------------------
4574 4494
4575 if (FLAG_debug_code) { 4495 if (FLAG_debug_code) {
4576 // The array construct code is only set for the global and natives 4496 // The array construct code is only set for the global and natives
4577 // builtin Array functions which always have maps. 4497 // builtin Array functions which always have maps.
4578 4498
4579 // Initial map for the builtin Array function should be a map. 4499 // Initial map for the builtin Array function should be a map.
4580 __ LoadP(r7, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 4500 __ LoadP(r6, FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
4581 // Will both indicate a NULL and a Smi. 4501 // Will both indicate a NULL and a Smi.
4582 __ TestIfSmi(r7, r0); 4502 __ TestIfSmi(r6);
4583 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0); 4503 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0);
4584 __ CompareObjectType(r7, r7, r8, MAP_TYPE); 4504 __ CompareObjectType(r6, r6, r7, MAP_TYPE);
4585 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 4505 __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
4586 4506
4587 // We should either have undefined in r5 or a valid AllocationSite 4507 // We should either have undefined in r4 or a valid AllocationSite
4588 __ AssertUndefinedOrAllocationSite(r5, r7); 4508 __ AssertUndefinedOrAllocationSite(r4, r6);
4589 } 4509 }
4590 4510
4591 // Enter the context of the Array function. 4511 // Enter the context of the Array function.
4592 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); 4512 __ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
4593 4513
4594 Label subclassing; 4514 Label subclassing;
4595 __ cmp(r6, r4); 4515 __ CmpP(r5, r3);
4596 __ bne(&subclassing); 4516 __ bne(&subclassing, Label::kNear);
4597 4517
4598 Label no_info; 4518 Label no_info;
4599 // Get the elements kind and case on that. 4519 // Get the elements kind and case on that.
4600 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); 4520 __ CompareRoot(r4, Heap::kUndefinedValueRootIndex);
4601 __ beq(&no_info); 4521 __ beq(&no_info);
4602 4522
4603 __ LoadP(r6, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset)); 4523 __ LoadP(r5, FieldMemOperand(r4, AllocationSite::kTransitionInfoOffset));
4604 __ SmiUntag(r6); 4524 __ SmiUntag(r5);
4605 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4525 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4606 __ And(r6, r6, Operand(AllocationSite::ElementsKindBits::kMask)); 4526 __ AndP(r5, Operand(AllocationSite::ElementsKindBits::kMask));
4607 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 4527 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
4608 4528
4609 __ bind(&no_info); 4529 __ bind(&no_info);
4610 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 4530 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
4611 4531
4612 __ bind(&subclassing); 4532 __ bind(&subclassing);
4613 switch (argument_count()) { 4533 switch (argument_count()) {
4614 case ANY: 4534 case ANY:
4615 case MORE_THAN_ONE: 4535 case MORE_THAN_ONE:
4616 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); 4536 __ ShiftLeftP(r1, r2, Operand(kPointerSizeLog2));
4617 __ StorePX(r4, MemOperand(sp, r0)); 4537 __ StoreP(r3, MemOperand(sp, r1));
4618 __ addi(r3, r3, Operand(3)); 4538 __ AddP(r2, r2, Operand(3));
4619 break; 4539 break;
4620 case NONE: 4540 case NONE:
4621 __ StoreP(r4, MemOperand(sp, 0 * kPointerSize)); 4541 __ StoreP(r3, MemOperand(sp, 0 * kPointerSize));
4622 __ li(r3, Operand(3)); 4542 __ LoadImmP(r2, Operand(3));
4623 break; 4543 break;
4624 case ONE: 4544 case ONE:
4625 __ StoreP(r4, MemOperand(sp, 1 * kPointerSize)); 4545 __ StoreP(r3, MemOperand(sp, 1 * kPointerSize));
4626 __ li(r3, Operand(4)); 4546 __ LoadImmP(r2, Operand(4));
4627 break; 4547 break;
4628 } 4548 }
4629 4549
4630 __ Push(r6, r5); 4550 __ Push(r5, r4);
4631 __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate())); 4551 __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate()));
4632 } 4552 }
4633 4553
4634
4635 void InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm, 4554 void InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm,
4636 ElementsKind kind) { 4555 ElementsKind kind) {
4637 __ cmpli(r3, Operand(1)); 4556 __ CmpLogicalP(r2, Operand(1));
4638 4557
4639 InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 4558 InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
4640 __ TailCallStub(&stub0, lt); 4559 __ TailCallStub(&stub0, lt);
4641 4560
4642 InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); 4561 InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
4643 __ TailCallStub(&stubN, gt); 4562 __ TailCallStub(&stubN, gt);
4644 4563
4645 if (IsFastPackedElementsKind(kind)) { 4564 if (IsFastPackedElementsKind(kind)) {
4646 // We might need to create a holey array 4565 // We might need to create a holey array
4647 // look at the first argument 4566 // look at the first argument
4648 __ LoadP(r6, MemOperand(sp, 0)); 4567 __ LoadP(r5, MemOperand(sp, 0));
4649 __ cmpi(r6, Operand::Zero()); 4568 __ CmpP(r5, Operand::Zero());
4650 4569
4651 InternalArraySingleArgumentConstructorStub stub1_holey( 4570 InternalArraySingleArgumentConstructorStub stub1_holey(
4652 isolate(), GetHoleyElementsKind(kind)); 4571 isolate(), GetHoleyElementsKind(kind));
4653 __ TailCallStub(&stub1_holey, ne); 4572 __ TailCallStub(&stub1_holey, ne);
4654 } 4573 }
4655 4574
4656 InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 4575 InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
4657 __ TailCallStub(&stub1); 4576 __ TailCallStub(&stub1);
4658 } 4577 }
4659 4578
4660
4661 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 4579 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
4662 // ----------- S t a t e ------------- 4580 // ----------- S t a t e -------------
4663 // -- r3 : argc 4581 // -- r2 : argc
4664 // -- r4 : constructor 4582 // -- r3 : constructor
4665 // -- sp[0] : return address 4583 // -- sp[0] : return address
4666 // -- sp[4] : last argument 4584 // -- sp[4] : last argument
4667 // ----------------------------------- 4585 // -----------------------------------
4668 4586
4669 if (FLAG_debug_code) { 4587 if (FLAG_debug_code) {
4670 // The array construct code is only set for the global and natives 4588 // The array construct code is only set for the global and natives
4671 // builtin Array functions which always have maps. 4589 // builtin Array functions which always have maps.
4672 4590
4673 // Initial map for the builtin Array function should be a map. 4591 // Initial map for the builtin Array function should be a map.
4674 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 4592 __ LoadP(r5, FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
4675 // Will both indicate a NULL and a Smi. 4593 // Will both indicate a NULL and a Smi.
4676 __ TestIfSmi(r6, r0); 4594 __ TestIfSmi(r5);
4677 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0); 4595 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0);
4678 __ CompareObjectType(r6, r6, r7, MAP_TYPE); 4596 __ CompareObjectType(r5, r5, r6, MAP_TYPE);
4679 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 4597 __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
4680 } 4598 }
4681 4599
4682 // Figure out the right elements kind 4600 // Figure out the right elements kind
4683 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); 4601 __ LoadP(r5, FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
4684 // Load the map's "bit field 2" into |result|. 4602 // Load the map's "bit field 2" into |result|.
4685 __ lbz(r6, FieldMemOperand(r6, Map::kBitField2Offset)); 4603 __ LoadlB(r5, FieldMemOperand(r5, Map::kBitField2Offset));
4686 // Retrieve elements_kind from bit field 2. 4604 // Retrieve elements_kind from bit field 2.
4687 __ DecodeField<Map::ElementsKindBits>(r6); 4605 __ DecodeField<Map::ElementsKindBits>(r5);
4688 4606
4689 if (FLAG_debug_code) { 4607 if (FLAG_debug_code) {
4690 Label done; 4608 Label done;
4691 __ cmpi(r6, Operand(FAST_ELEMENTS)); 4609 __ CmpP(r5, Operand(FAST_ELEMENTS));
4692 __ beq(&done); 4610 __ beq(&done);
4693 __ cmpi(r6, Operand(FAST_HOLEY_ELEMENTS)); 4611 __ CmpP(r5, Operand(FAST_HOLEY_ELEMENTS));
4694 __ Assert(eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray); 4612 __ Assert(eq, kInvalidElementsKindForInternalArrayOrInternalPackedArray);
4695 __ bind(&done); 4613 __ bind(&done);
4696 } 4614 }
4697 4615
4698 Label fast_elements_case; 4616 Label fast_elements_case;
4699 __ cmpi(r6, Operand(FAST_ELEMENTS)); 4617 __ CmpP(r5, Operand(FAST_ELEMENTS));
4700 __ beq(&fast_elements_case); 4618 __ beq(&fast_elements_case);
4701 GenerateCase(masm, FAST_HOLEY_ELEMENTS); 4619 GenerateCase(masm, FAST_HOLEY_ELEMENTS);
4702 4620
4703 __ bind(&fast_elements_case); 4621 __ bind(&fast_elements_case);
4704 GenerateCase(masm, FAST_ELEMENTS); 4622 GenerateCase(masm, FAST_ELEMENTS);
4705 } 4623 }
4706 4624
4707 void FastNewObjectStub::Generate(MacroAssembler* masm) { 4625 void FastNewObjectStub::Generate(MacroAssembler* masm) {
4708 // ----------- S t a t e ------------- 4626 // ----------- S t a t e -------------
4709 // -- r4 : target 4627 // -- r3 : target
4710 // -- r6 : new target 4628 // -- r5 : new target
4711 // -- cp : context 4629 // -- cp : context
4712 // -- lr : return address 4630 // -- lr : return address
4713 // ----------------------------------- 4631 // -----------------------------------
4714 __ AssertFunction(r4); 4632 __ AssertFunction(r3);
4715 __ AssertReceiver(r6); 4633 __ AssertReceiver(r5);
4716 4634
4717 // Verify that the new target is a JSFunction. 4635 // Verify that the new target is a JSFunction.
4718 Label new_object; 4636 Label new_object;
4719 __ CompareObjectType(r6, r5, r5, JS_FUNCTION_TYPE); 4637 __ CompareObjectType(r5, r4, r4, JS_FUNCTION_TYPE);
4720 __ bne(&new_object); 4638 __ bne(&new_object);
4721 4639
4722 // Load the initial map and verify that it's in fact a map. 4640 // Load the initial map and verify that it's in fact a map.
4723 __ LoadP(r5, FieldMemOperand(r6, JSFunction::kPrototypeOrInitialMapOffset)); 4641 __ LoadP(r4, FieldMemOperand(r5, JSFunction::kPrototypeOrInitialMapOffset));
4724 __ JumpIfSmi(r5, &new_object); 4642 __ JumpIfSmi(r4, &new_object);
4725 __ CompareObjectType(r5, r3, r3, MAP_TYPE); 4643 __ CompareObjectType(r4, r2, r2, MAP_TYPE);
4726 __ bne(&new_object); 4644 __ bne(&new_object);
4727 4645
4728 // Fall back to runtime if the target differs from the new target's 4646 // Fall back to runtime if the target differs from the new target's
4729 // initial map constructor. 4647 // initial map constructor.
4730 __ LoadP(r3, FieldMemOperand(r5, Map::kConstructorOrBackPointerOffset)); 4648 __ LoadP(r2, FieldMemOperand(r4, Map::kConstructorOrBackPointerOffset));
4731 __ cmp(r3, r4); 4649 __ CmpP(r2, r3);
4732 __ bne(&new_object); 4650 __ bne(&new_object);
4733 4651
4734 // Allocate the JSObject on the heap. 4652 // Allocate the JSObject on the heap.
4735 Label allocate, done_allocate; 4653 Label allocate, done_allocate;
4736 __ lbz(r7, FieldMemOperand(r5, Map::kInstanceSizeOffset)); 4654 __ LoadlB(r6, FieldMemOperand(r4, Map::kInstanceSizeOffset));
4737 __ Allocate(r7, r3, r8, r9, &allocate, SIZE_IN_WORDS); 4655 __ Allocate(r6, r2, r7, r8, &allocate, SIZE_IN_WORDS);
4738 __ bind(&done_allocate); 4656 __ bind(&done_allocate);
4739 4657
4740 // Initialize the JSObject fields. 4658 // Initialize the JSObject fields.
4741 __ StoreP(r5, MemOperand(r3, JSObject::kMapOffset)); 4659 __ StoreP(r4, MemOperand(r2, JSObject::kMapOffset));
4742 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 4660 __ LoadRoot(r5, Heap::kEmptyFixedArrayRootIndex);
4743 __ StoreP(r6, MemOperand(r3, JSObject::kPropertiesOffset)); 4661 __ StoreP(r5, MemOperand(r2, JSObject::kPropertiesOffset));
4744 __ StoreP(r6, MemOperand(r3, JSObject::kElementsOffset)); 4662 __ StoreP(r5, MemOperand(r2, JSObject::kElementsOffset));
4745 STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize); 4663 STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
4746 __ addi(r4, r3, Operand(JSObject::kHeaderSize)); 4664 __ AddP(r3, r2, Operand(JSObject::kHeaderSize));
4747 4665
4748 // ----------- S t a t e ------------- 4666 // ----------- S t a t e -------------
4749 // -- r3 : result (untagged) 4667 // -- r2 : result (untagged)
4750 // -- r4 : result fields (untagged) 4668 // -- r3 : result fields (untagged)
4751 // -- r8 : result end (untagged) 4669 // -- r7 : result end (untagged)
4752 // -- r5 : initial map 4670 // -- r4 : initial map
4753 // -- cp : context 4671 // -- cp : context
4754 // -- lr : return address 4672 // -- lr : return address
4755 // ----------------------------------- 4673 // -----------------------------------
4756 4674
4757 // Perform in-object slack tracking if requested. 4675 // Perform in-object slack tracking if requested.
4758 Label slack_tracking; 4676 Label slack_tracking;
4759 STATIC_ASSERT(Map::kNoSlackTracking == 0); 4677 STATIC_ASSERT(Map::kNoSlackTracking == 0);
4760 __ LoadRoot(r9, Heap::kUndefinedValueRootIndex); 4678 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
4761 __ lwz(r6, FieldMemOperand(r5, Map::kBitField3Offset)); 4679 __ LoadlW(r5, FieldMemOperand(r4, Map::kBitField3Offset));
4762 __ DecodeField<Map::ConstructionCounter>(r10, r6, SetRC); 4680 __ DecodeField<Map::ConstructionCounter>(r9, r5);
4763 __ bne(&slack_tracking, cr0); 4681 __ LoadAndTestP(r9, r9);
4682 __ bne(&slack_tracking);
4764 { 4683 {
4765 // Initialize all in-object fields with undefined. 4684 // Initialize all in-object fields with undefined.
4766 __ InitializeFieldsWithFiller(r4, r8, r9); 4685 __ InitializeFieldsWithFiller(r3, r7, r8);
4767 4686
4768 // Add the object tag to make the JSObject real. 4687 // Add the object tag to make the JSObject real.
4769 __ addi(r3, r3, Operand(kHeapObjectTag)); 4688 __ AddP(r2, r2, Operand(kHeapObjectTag));
4770 __ Ret(); 4689 __ Ret();
4771 } 4690 }
4772 __ bind(&slack_tracking); 4691 __ bind(&slack_tracking);
4773 { 4692 {
4774 // Decrease generous allocation count. 4693 // Decrease generous allocation count.
4775 STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); 4694 STATIC_ASSERT(Map::ConstructionCounter::kNext == 32);
4776 __ Add(r6, r6, -(1 << Map::ConstructionCounter::kShift), r0); 4695 __ Add32(r5, r5, Operand(-(1 << Map::ConstructionCounter::kShift)));
4777 __ stw(r6, FieldMemOperand(r5, Map::kBitField3Offset)); 4696 __ StoreW(r5, FieldMemOperand(r4, Map::kBitField3Offset));
4778 4697
4779 // Initialize the in-object fields with undefined. 4698 // Initialize the in-object fields with undefined.
4780 __ lbz(r7, FieldMemOperand(r5, Map::kUnusedPropertyFieldsOffset)); 4699 __ LoadlB(r6, FieldMemOperand(r4, Map::kUnusedPropertyFieldsOffset));
4781 __ ShiftLeftImm(r7, r7, Operand(kPointerSizeLog2)); 4700 __ ShiftLeftP(r6, r6, Operand(kPointerSizeLog2));
4782 __ sub(r7, r8, r7); 4701 __ SubP(r6, r7, r6);
4783 __ InitializeFieldsWithFiller(r4, r7, r9); 4702 __ InitializeFieldsWithFiller(r3, r6, r8);
4784 4703
4785 // Initialize the remaining (reserved) fields with one pointer filler map. 4704 // Initialize the remaining (reserved) fields with one pointer filler map.
4786 __ LoadRoot(r9, Heap::kOnePointerFillerMapRootIndex); 4705 __ LoadRoot(r8, Heap::kOnePointerFillerMapRootIndex);
4787 __ InitializeFieldsWithFiller(r4, r8, r9); 4706 __ InitializeFieldsWithFiller(r3, r7, r8);
4788 4707
4789 // Add the object tag to make the JSObject real. 4708 // Add the object tag to make the JSObject real.
4790 __ addi(r3, r3, Operand(kHeapObjectTag)); 4709 __ AddP(r2, r2, Operand(kHeapObjectTag));
4791 4710
4792 // Check if we can finalize the instance size. 4711 // Check if we can finalize the instance size.
4793 __ cmpi(r10, Operand(Map::kSlackTrackingCounterEnd)); 4712 __ CmpP(r9, Operand(Map::kSlackTrackingCounterEnd));
4794 __ Ret(ne); 4713 __ Ret(ne);
4795 4714
4796 // Finalize the instance size. 4715 // Finalize the instance size.
4797 { 4716 {
4798 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4717 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
4799 __ Push(r3, r5); 4718 __ Push(r2, r4);
4800 __ CallRuntime(Runtime::kFinalizeInstanceSize); 4719 __ CallRuntime(Runtime::kFinalizeInstanceSize);
4801 __ Pop(r3); 4720 __ Pop(r2);
4802 } 4721 }
4803 __ Ret(); 4722 __ Ret();
4804 } 4723 }
4805 4724
4806 // Fall back to %AllocateInNewSpace. 4725 // Fall back to %AllocateInNewSpace.
4807 __ bind(&allocate); 4726 __ bind(&allocate);
4808 { 4727 {
4809 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4728 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
4810 STATIC_ASSERT(kSmiTag == 0); 4729 STATIC_ASSERT(kSmiTag == 0);
4811 __ ShiftLeftImm(r7, r7, 4730 __ ShiftLeftP(r6, r6,
4812 Operand(kPointerSizeLog2 + kSmiTagSize + kSmiShiftSize)); 4731 Operand(kPointerSizeLog2 + kSmiTagSize + kSmiShiftSize));
4813 __ Push(r5, r7); 4732 __ Push(r4, r6);
4814 __ CallRuntime(Runtime::kAllocateInNewSpace); 4733 __ CallRuntime(Runtime::kAllocateInNewSpace);
4815 __ Pop(r5); 4734 __ Pop(r4);
4816 } 4735 }
4817 __ subi(r3, r3, Operand(kHeapObjectTag)); 4736 __ SubP(r2, r2, Operand(kHeapObjectTag));
4818 __ lbz(r8, FieldMemOperand(r5, Map::kInstanceSizeOffset)); 4737 __ LoadlB(r7, FieldMemOperand(r4, Map::kInstanceSizeOffset));
4819 __ ShiftLeftImm(r8, r8, Operand(kPointerSizeLog2)); 4738 __ ShiftLeftP(r7, r7, Operand(kPointerSizeLog2));
4820 __ add(r8, r3, r8); 4739 __ AddP(r7, r2, r7);
4821 __ b(&done_allocate); 4740 __ b(&done_allocate);
4822 4741
4823 // Fall back to %NewObject. 4742 // Fall back to %NewObject.
4824 __ bind(&new_object); 4743 __ bind(&new_object);
4825 __ Push(r4, r6); 4744 __ Push(r3, r5);
4826 __ TailCallRuntime(Runtime::kNewObject); 4745 __ TailCallRuntime(Runtime::kNewObject);
4827 } 4746 }
4828 4747
4829 void FastNewRestParameterStub::Generate(MacroAssembler* masm) { 4748 void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
4830 // ----------- S t a t e ------------- 4749 // ----------- S t a t e -------------
4831 // -- r4 : function 4750 // -- r3 : function
4832 // -- cp : context 4751 // -- cp : context
4833 // -- fp : frame pointer 4752 // -- fp : frame pointer
4834 // -- lr : return address 4753 // -- lr : return address
4835 // ----------------------------------- 4754 // -----------------------------------
4836 __ AssertFunction(r4); 4755 __ AssertFunction(r3);
4837 4756
4838 // For Ignition we need to skip all possible handler/stub frames until 4757 // For Ignition we need to skip all possible handler/stub frames until
4839 // we reach the JavaScript frame for the function (similar to what the 4758 // we reach the JavaScript frame for the function (similar to what the
4840 // runtime fallback implementation does). So make r5 point to that 4759 // runtime fallback implementation does). So make r4 point to that
4841 // JavaScript frame. 4760 // JavaScript frame.
4842 { 4761 {
4843 Label loop, loop_entry; 4762 Label loop, loop_entry;
4844 __ mr(r5, fp); 4763 __ LoadRR(r4, fp);
4845 __ b(&loop_entry); 4764 __ b(&loop_entry);
4846 __ bind(&loop); 4765 __ bind(&loop);
4847 __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 4766 __ LoadP(r4, MemOperand(r4, StandardFrameConstants::kCallerFPOffset));
4848 __ bind(&loop_entry); 4767 __ bind(&loop_entry);
4849 __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kMarkerOffset)); 4768 __ LoadP(ip, MemOperand(r4, StandardFrameConstants::kMarkerOffset));
4850 __ cmp(ip, r4); 4769 __ CmpP(ip, r3);
4851 __ bne(&loop); 4770 __ bne(&loop);
4852 } 4771 }
4853 4772
4854 // Check if we have rest parameters (only possible if we have an 4773 // Check if we have rest parameters (only possible if we have an
4855 // arguments adaptor frame below the function frame). 4774 // arguments adaptor frame below the function frame).
4856 Label no_rest_parameters; 4775 Label no_rest_parameters;
4857 __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 4776 __ LoadP(r4, MemOperand(r4, StandardFrameConstants::kCallerFPOffset));
4858 __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kContextOffset)); 4777 __ LoadP(ip, MemOperand(r4, StandardFrameConstants::kContextOffset));
4859 __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); 4778 __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
4860 __ bne(&no_rest_parameters); 4779 __ bne(&no_rest_parameters);
4861 4780
4862 // Check if the arguments adaptor frame contains more arguments than 4781 // Check if the arguments adaptor frame contains more arguments than
4863 // specified by the function's internal formal parameter count. 4782 // specified by the function's internal formal parameter count.
4864 Label rest_parameters; 4783 Label rest_parameters;
4865 __ LoadP(r3, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4784 __ LoadP(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset));
4866 __ LoadP(r4, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 4785 __ LoadP(r3, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
4867 __ LoadWordArith( 4786 __ LoadW(
4868 r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset)); 4787 r3, FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
4869 #if V8_TARGET_ARCH_PPC64 4788 #if V8_TARGET_ARCH_S390X
4870 __ SmiTag(r4); 4789 __ SmiTag(r3);
4871 #endif 4790 #endif
4872 __ sub(r3, r3, r4, LeaveOE, SetRC); 4791 __ SubP(r2, r2, r3);
4873 __ bgt(&rest_parameters, cr0); 4792 __ bgt(&rest_parameters);
4874 4793
4875 // Return an empty rest parameter array. 4794 // Return an empty rest parameter array.
4876 __ bind(&no_rest_parameters); 4795 __ bind(&no_rest_parameters);
4877 { 4796 {
4878 // ----------- S t a t e ------------- 4797 // ----------- S t a t e -------------
4879 // -- cp : context 4798 // -- cp : context
4880 // -- lr : return address 4799 // -- lr : return address
4881 // ----------------------------------- 4800 // -----------------------------------
4882 4801
4883 // Allocate an empty rest parameter array. 4802 // Allocate an empty rest parameter array.
4884 Label allocate, done_allocate; 4803 Label allocate, done_allocate;
4885 __ Allocate(JSArray::kSize, r3, r4, r5, &allocate, TAG_OBJECT); 4804 __ Allocate(JSArray::kSize, r2, r3, r4, &allocate, TAG_OBJECT);
4886 __ bind(&done_allocate); 4805 __ bind(&done_allocate);
4887 4806
4888 // Setup the rest parameter array in r0. 4807 // Setup the rest parameter array in r0.
4889 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r4); 4808 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r3);
4890 __ StoreP(r4, FieldMemOperand(r3, JSArray::kMapOffset), r0); 4809 __ StoreP(r3, FieldMemOperand(r2, JSArray::kMapOffset), r0);
4891 __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 4810 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
4892 __ StoreP(r4, FieldMemOperand(r3, JSArray::kPropertiesOffset), r0); 4811 __ StoreP(r3, FieldMemOperand(r2, JSArray::kPropertiesOffset), r0);
4893 __ StoreP(r4, FieldMemOperand(r3, JSArray::kElementsOffset), r0); 4812 __ StoreP(r3, FieldMemOperand(r2, JSArray::kElementsOffset), r0);
4894 __ li(r4, Operand::Zero()); 4813 __ LoadImmP(r3, Operand::Zero());
4895 __ StoreP(r4, FieldMemOperand(r3, JSArray::kLengthOffset), r0); 4814 __ StoreP(r3, FieldMemOperand(r2, JSArray::kLengthOffset), r0);
4896 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); 4815 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
4897 __ Ret(); 4816 __ Ret();
4898 4817
4899 // Fall back to %AllocateInNewSpace. 4818 // Fall back to %AllocateInNewSpace.
4900 __ bind(&allocate); 4819 __ bind(&allocate);
4901 { 4820 {
4902 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4821 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
4903 __ Push(Smi::FromInt(JSArray::kSize)); 4822 __ Push(Smi::FromInt(JSArray::kSize));
4904 __ CallRuntime(Runtime::kAllocateInNewSpace); 4823 __ CallRuntime(Runtime::kAllocateInNewSpace);
4905 } 4824 }
4906 __ b(&done_allocate); 4825 __ b(&done_allocate);
4907 } 4826 }
4908 4827
4909 __ bind(&rest_parameters); 4828 __ bind(&rest_parameters);
4910 { 4829 {
4911 // Compute the pointer to the first rest parameter (skippping the receiver). 4830 // Compute the pointer to the first rest parameter (skippping the receiver).
4912 __ SmiToPtrArrayOffset(r9, r3); 4831 __ SmiToPtrArrayOffset(r8, r2);
4913 __ add(r5, r5, r9); 4832 __ AddP(r4, r4, r8);
4914 __ addi(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset)); 4833 __ AddP(r4, r4, Operand(StandardFrameConstants::kCallerSPOffset));
4915 4834
4916 // ----------- S t a t e ------------- 4835 // ----------- S t a t e -------------
4917 // -- cp : context 4836 // -- cp : context
4918 // -- r3 : number of rest parameters (tagged) 4837 // -- r2 : number of rest parameters (tagged)
4919 // -- r5 : pointer just past first rest parameters 4838 // -- r4 : pointer just past first rest parameters
4920 // -- r9 : size of rest parameters 4839 // -- r8 : size of rest parameters
4921 // -- lr : return address 4840 // -- lr : return address
4922 // ----------------------------------- 4841 // -----------------------------------
4923 4842
4924 // Allocate space for the rest parameter array plus the backing store. 4843 // Allocate space for the rest parameter array plus the backing store.
4925 Label allocate, done_allocate; 4844 Label allocate, done_allocate;
4926 __ mov(r4, Operand(JSArray::kSize + FixedArray::kHeaderSize)); 4845 __ mov(r3, Operand(JSArray::kSize + FixedArray::kHeaderSize));
4927 __ add(r4, r4, r9); 4846 __ AddP(r3, r3, r8);
4928 __ Allocate(r4, r6, r7, r8, &allocate, TAG_OBJECT); 4847 __ Allocate(r3, r5, r6, r7, &allocate, TAG_OBJECT);
4929 __ bind(&done_allocate); 4848 __ bind(&done_allocate);
4930 4849
4931 // Setup the elements array in r6. 4850 // Setup the elements array in r5.
4932 __ LoadRoot(r4, Heap::kFixedArrayMapRootIndex); 4851 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
4933 __ StoreP(r4, FieldMemOperand(r6, FixedArray::kMapOffset), r0); 4852 __ StoreP(r3, FieldMemOperand(r5, FixedArray::kMapOffset), r0);
4934 __ StoreP(r3, FieldMemOperand(r6, FixedArray::kLengthOffset), r0); 4853 __ StoreP(r2, FieldMemOperand(r5, FixedArray::kLengthOffset), r0);
4935 __ addi(r7, r6, 4854 __ AddP(r6, r5,
4936 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); 4855 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
4937 { 4856 {
4938 Label loop; 4857 Label loop;
4939 __ SmiUntag(r0, r3); 4858 __ SmiUntag(r1, r2);
4940 __ mtctr(r0); 4859 // __ mtctr(r0);
4941 __ bind(&loop); 4860 __ bind(&loop);
4942 __ LoadPU(ip, MemOperand(r5, -kPointerSize)); 4861 __ lay(r4, MemOperand(r4, -kPointerSize));
4943 __ StorePU(ip, MemOperand(r7, kPointerSize)); 4862 __ LoadP(ip, MemOperand(r4));
4944 __ bdnz(&loop); 4863 __ la(r6, MemOperand(r6, kPointerSize));
4945 __ addi(r7, r7, Operand(kPointerSize)); 4864 __ StoreP(ip, MemOperand(r6));
4865 // __ bdnz(&loop);
4866 __ BranchOnCount(r1, &loop);
4867 __ AddP(r6, r6, Operand(kPointerSize));
4946 } 4868 }
4947 4869
4948 // Setup the rest parameter array in r7. 4870 // Setup the rest parameter array in r6.
4949 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r4); 4871 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, r3);
4950 __ StoreP(r4, MemOperand(r7, JSArray::kMapOffset)); 4872 __ StoreP(r3, MemOperand(r6, JSArray::kMapOffset));
4951 __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 4873 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
4952 __ StoreP(r4, MemOperand(r7, JSArray::kPropertiesOffset)); 4874 __ StoreP(r3, MemOperand(r6, JSArray::kPropertiesOffset));
4953 __ StoreP(r6, MemOperand(r7, JSArray::kElementsOffset)); 4875 __ StoreP(r5, MemOperand(r6, JSArray::kElementsOffset));
4954 __ StoreP(r3, MemOperand(r7, JSArray::kLengthOffset)); 4876 __ StoreP(r2, MemOperand(r6, JSArray::kLengthOffset));
4955 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); 4877 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
4956 __ addi(r3, r7, Operand(kHeapObjectTag)); 4878 __ AddP(r2, r6, Operand(kHeapObjectTag));
4957 __ Ret(); 4879 __ Ret();
4958 4880
4959 // Fall back to %AllocateInNewSpace. 4881 // Fall back to %AllocateInNewSpace.
4960 __ bind(&allocate); 4882 __ bind(&allocate);
4961 { 4883 {
4962 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4884 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
4963 __ SmiTag(r4); 4885 __ SmiTag(r3);
4964 __ Push(r3, r5, r4); 4886 __ Push(r2, r4, r3);
4965 __ CallRuntime(Runtime::kAllocateInNewSpace); 4887 __ CallRuntime(Runtime::kAllocateInNewSpace);
4966 __ mr(r6, r3); 4888 __ LoadRR(r5, r2);
4967 __ Pop(r3, r5); 4889 __ Pop(r2, r4);
4968 } 4890 }
4969 __ b(&done_allocate); 4891 __ b(&done_allocate);
4970 } 4892 }
4971 } 4893 }
4972 4894
4973 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { 4895 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) {
4974 // ----------- S t a t e ------------- 4896 // ----------- S t a t e -------------
4975 // -- r4 : function 4897 // -- r3 : function
4976 // -- cp : context 4898 // -- cp : context
4977 // -- fp : frame pointer 4899 // -- fp : frame pointer
4978 // -- lr : return address 4900 // -- lr : return address
4979 // ----------------------------------- 4901 // -----------------------------------
4980 __ AssertFunction(r4); 4902 __ AssertFunction(r3);
4981 4903
4982 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. 4904 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
4983 __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 4905 __ LoadP(r4, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
4984 __ LoadWordArith( 4906 __ LoadW(
4985 r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset)); 4907 r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset));
4986 #if V8_TARGET_ARCH_PPC64 4908 #if V8_TARGET_ARCH_S390X
4987 __ SmiTag(r5); 4909 __ SmiTag(r4);
4988 #endif 4910 #endif
4989 __ SmiToPtrArrayOffset(r6, r5); 4911 __ SmiToPtrArrayOffset(r5, r4);
4990 __ add(r6, fp, r6); 4912 __ AddP(r5, fp, r5);
4991 __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset)); 4913 __ AddP(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset));
4992 4914
4993 // r4 : function 4915 // r3 : function
4994 // r5 : number of parameters (tagged) 4916 // r4 : number of parameters (tagged)
4995 // r6 : parameters pointer 4917 // r5 : parameters pointer
4996 // Registers used over whole function: 4918 // Registers used over whole function:
4997 // r8 : arguments count (tagged) 4919 // r7 : arguments count (tagged)
4998 // r9 : mapped parameter count (tagged) 4920 // r8 : mapped parameter count (tagged)
4999 4921
5000 // Check if the calling frame is an arguments adaptor frame. 4922 // Check if the calling frame is an arguments adaptor frame.
5001 Label adaptor_frame, try_allocate, runtime; 4923 Label adaptor_frame, try_allocate, runtime;
5002 __ LoadP(r7, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 4924 __ LoadP(r6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5003 __ LoadP(r3, MemOperand(r7, StandardFrameConstants::kContextOffset)); 4925 __ LoadP(r2, MemOperand(r6, StandardFrameConstants::kContextOffset));
5004 __ CmpSmiLiteral(r3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); 4926 __ CmpSmiLiteral(r2, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
5005 __ beq(&adaptor_frame); 4927 __ beq(&adaptor_frame);
5006 4928
5007 // No adaptor, parameter count = argument count. 4929 // No adaptor, parameter count = argument count.
5008 __ mr(r8, r5); 4930 __ LoadRR(r7, r4);
5009 __ mr(r9, r5); 4931 __ LoadRR(r8, r4);
5010 __ b(&try_allocate); 4932 __ b(&try_allocate);
5011 4933
5012 // We have an adaptor frame. Patch the parameters pointer. 4934 // We have an adaptor frame. Patch the parameters pointer.
5013 __ bind(&adaptor_frame); 4935 __ bind(&adaptor_frame);
5014 __ LoadP(r8, MemOperand(r7, ArgumentsAdaptorFrameConstants::kLengthOffset)); 4936 __ LoadP(r7, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset));
5015 __ SmiToPtrArrayOffset(r6, r8); 4937 __ SmiToPtrArrayOffset(r5, r7);
5016 __ add(r6, r6, r7); 4938 __ AddP(r5, r5, r6);
5017 __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset)); 4939 __ AddP(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset));
5018 4940
5019 // r8 = argument count (tagged) 4941 // r7 = argument count (tagged)
5020 // r9 = parameter count (tagged) 4942 // r8 = parameter count (tagged)
5021 // Compute the mapped parameter count = min(r5, r8) in r9. 4943 // Compute the mapped parameter count = min(r4, r7) in r8.
5022 __ cmp(r5, r8); 4944 __ CmpP(r4, r7);
5023 if (CpuFeatures::IsSupported(ISELECT)) { 4945 Label skip;
5024 __ isel(lt, r9, r5, r8); 4946 __ LoadRR(r8, r4);
5025 } else { 4947 __ blt(&skip);
5026 Label skip; 4948 __ LoadRR(r8, r7);
5027 __ mr(r9, r5); 4949 __ bind(&skip);
5028 __ blt(&skip);
5029 __ mr(r9, r8);
5030 __ bind(&skip);
5031 }
5032 4950
5033 __ bind(&try_allocate); 4951 __ bind(&try_allocate);
5034 4952
5035 // Compute the sizes of backing store, parameter map, and arguments object. 4953 // Compute the sizes of backing store, parameter map, and arguments object.
5036 // 1. Parameter map, has 2 extra words containing context and backing store. 4954 // 1. Parameter map, has 2 extra words containing context and backing store.
5037 const int kParameterMapHeaderSize = 4955 const int kParameterMapHeaderSize =
5038 FixedArray::kHeaderSize + 2 * kPointerSize; 4956 FixedArray::kHeaderSize + 2 * kPointerSize;
5039 // If there are no mapped parameters, we do not need the parameter_map. 4957 // If there are no mapped parameters, we do not need the parameter_map.
5040 __ CmpSmiLiteral(r9, Smi::FromInt(0), r0); 4958 __ CmpSmiLiteral(r8, Smi::FromInt(0), r0);
5041 if (CpuFeatures::IsSupported(ISELECT)) { 4959 Label skip2, skip3;
5042 __ SmiToPtrArrayOffset(r11, r9); 4960 __ bne(&skip2);
5043 __ addi(r11, r11, Operand(kParameterMapHeaderSize)); 4961 __ LoadImmP(r1, Operand::Zero());
5044 __ isel(eq, r11, r0, r11); 4962 __ b(&skip3);
5045 } else { 4963 __ bind(&skip2);
5046 Label skip2, skip3; 4964 __ SmiToPtrArrayOffset(r1, r8);
5047 __ bne(&skip2); 4965 __ AddP(r1, r1, Operand(kParameterMapHeaderSize));
5048 __ li(r11, Operand::Zero()); 4966 __ bind(&skip3);
5049 __ b(&skip3);
5050 __ bind(&skip2);
5051 __ SmiToPtrArrayOffset(r11, r9);
5052 __ addi(r11, r11, Operand(kParameterMapHeaderSize));
5053 __ bind(&skip3);
5054 }
5055 4967
5056 // 2. Backing store. 4968 // 2. Backing store.
5057 __ SmiToPtrArrayOffset(r7, r8); 4969 __ SmiToPtrArrayOffset(r6, r7);
5058 __ add(r11, r11, r7); 4970 __ AddP(r1, r1, r6);
5059 __ addi(r11, r11, Operand(FixedArray::kHeaderSize)); 4971 __ AddP(r1, r1, Operand(FixedArray::kHeaderSize));
5060 4972
5061 // 3. Arguments object. 4973 // 3. Arguments object.
5062 __ addi(r11, r11, Operand(JSSloppyArgumentsObject::kSize)); 4974 __ AddP(r1, r1, Operand(JSSloppyArgumentsObject::kSize));
5063 4975
5064 // Do the allocation of all three objects in one go. 4976 // Do the allocation of all three objects in one go.
5065 __ Allocate(r11, r3, r11, r7, &runtime, TAG_OBJECT); 4977 __ Allocate(r1, r2, r1, r6, &runtime, TAG_OBJECT);
5066 4978
5067 // r3 = address of new object(s) (tagged) 4979 // r2 = address of new object(s) (tagged)
5068 // r5 = argument count (smi-tagged) 4980 // r4 = argument count (smi-tagged)
5069 // Get the arguments boilerplate from the current native context into r4. 4981 // Get the arguments boilerplate from the current native context into r3.
5070 const int kNormalOffset = 4982 const int kNormalOffset =
5071 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); 4983 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX);
5072 const int kAliasedOffset = 4984 const int kAliasedOffset =
5073 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); 4985 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX);
5074 4986
5075 __ LoadP(r7, NativeContextMemOperand()); 4987 __ LoadP(r6, NativeContextMemOperand());
5076 __ cmpi(r9, Operand::Zero()); 4988 __ CmpP(r8, Operand::Zero());
5077 if (CpuFeatures::IsSupported(ISELECT)) { 4989 Label skip4, skip5;
5078 __ LoadP(r11, MemOperand(r7, kNormalOffset)); 4990 __ bne(&skip4);
5079 __ LoadP(r7, MemOperand(r7, kAliasedOffset)); 4991 __ LoadP(r6, MemOperand(r6, kNormalOffset));
5080 __ isel(eq, r7, r11, r7); 4992 __ b(&skip5);
5081 } else { 4993 __ bind(&skip4);
5082 Label skip4, skip5; 4994 __ LoadP(r6, MemOperand(r6, kAliasedOffset));
5083 __ bne(&skip4); 4995 __ bind(&skip5);
5084 __ LoadP(r7, MemOperand(r7, kNormalOffset));
5085 __ b(&skip5);
5086 __ bind(&skip4);
5087 __ LoadP(r7, MemOperand(r7, kAliasedOffset));
5088 __ bind(&skip5);
5089 }
5090 4996
5091 // r3 = address of new object (tagged) 4997 // r2 = address of new object (tagged)
5092 // r5 = argument count (smi-tagged) 4998 // r4 = argument count (smi-tagged)
5093 // r7 = address of arguments map (tagged) 4999 // r6 = address of arguments map (tagged)
5094 // r9 = mapped parameter count (tagged) 5000 // r8 = mapped parameter count (tagged)
5095 __ StoreP(r7, FieldMemOperand(r3, JSObject::kMapOffset), r0); 5001 __ StoreP(r6, FieldMemOperand(r2, JSObject::kMapOffset), r0);
5096 __ LoadRoot(r11, Heap::kEmptyFixedArrayRootIndex); 5002 __ LoadRoot(r1, Heap::kEmptyFixedArrayRootIndex);
5097 __ StoreP(r11, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0); 5003 __ StoreP(r1, FieldMemOperand(r2, JSObject::kPropertiesOffset), r0);
5098 __ StoreP(r11, FieldMemOperand(r3, JSObject::kElementsOffset), r0); 5004 __ StoreP(r1, FieldMemOperand(r2, JSObject::kElementsOffset), r0);
5099 5005
5100 // Set up the callee in-object property. 5006 // Set up the callee in-object property.
5101 __ AssertNotSmi(r4); 5007 __ AssertNotSmi(r3);
5102 __ StoreP(r4, FieldMemOperand(r3, JSSloppyArgumentsObject::kCalleeOffset), 5008 __ StoreP(r3, FieldMemOperand(r2, JSSloppyArgumentsObject::kCalleeOffset),
5103 r0); 5009 r0);
5104 5010
5105 // Use the length (smi tagged) and set that as an in-object property too. 5011 // Use the length (smi tagged) and set that as an in-object property too.
5106 __ AssertSmi(r8); 5012 __ AssertSmi(r7);
5107 __ StoreP(r8, FieldMemOperand(r3, JSSloppyArgumentsObject::kLengthOffset), 5013 __ StoreP(r7, FieldMemOperand(r2, JSSloppyArgumentsObject::kLengthOffset),
5108 r0); 5014 r0);
5109 5015
5110 // Set up the elements pointer in the allocated arguments object. 5016 // Set up the elements pointer in the allocated arguments object.
5111 // If we allocated a parameter map, r7 will point there, otherwise 5017 // If we allocated a parameter map, r6 will point there, otherwise
5112 // it will point to the backing store. 5018 // it will point to the backing store.
5113 __ addi(r7, r3, Operand(JSSloppyArgumentsObject::kSize)); 5019 __ AddP(r6, r2, Operand(JSSloppyArgumentsObject::kSize));
5114 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0); 5020 __ StoreP(r6, FieldMemOperand(r2, JSObject::kElementsOffset), r0);
5115 5021
5116 // r3 = address of new object (tagged) 5022 // r2 = address of new object (tagged)
5117 // r5 = argument count (tagged) 5023 // r4 = argument count (tagged)
5118 // r7 = address of parameter map or backing store (tagged) 5024 // r6 = address of parameter map or backing store (tagged)
5119 // r9 = mapped parameter count (tagged) 5025 // r8 = mapped parameter count (tagged)
5120 // Initialize parameter map. If there are no mapped arguments, we're done. 5026 // Initialize parameter map. If there are no mapped arguments, we're done.
5121 Label skip_parameter_map; 5027 Label skip_parameter_map;
5122 __ CmpSmiLiteral(r9, Smi::FromInt(0), r0); 5028 __ CmpSmiLiteral(r8, Smi::FromInt(0), r0);
5123 if (CpuFeatures::IsSupported(ISELECT)) { 5029 Label skip6;
5124 __ isel(eq, r4, r7, r4); 5030 __ bne(&skip6);
5125 __ beq(&skip_parameter_map); 5031 // Move backing store address to r3, because it is
5126 } else { 5032 // expected there when filling in the unmapped arguments.
5127 Label skip6; 5033 __ LoadRR(r3, r6);
5128 __ bne(&skip6); 5034 __ b(&skip_parameter_map);
5129 // Move backing store address to r4, because it is 5035 __ bind(&skip6);
5130 // expected there when filling in the unmapped arguments.
5131 __ mr(r4, r7);
5132 __ b(&skip_parameter_map);
5133 __ bind(&skip6);
5134 }
5135 5036
5136 __ LoadRoot(r8, Heap::kSloppyArgumentsElementsMapRootIndex); 5037 __ LoadRoot(r7, Heap::kSloppyArgumentsElementsMapRootIndex);
5137 __ StoreP(r8, FieldMemOperand(r7, FixedArray::kMapOffset), r0); 5038 __ StoreP(r7, FieldMemOperand(r6, FixedArray::kMapOffset), r0);
5138 __ AddSmiLiteral(r8, r9, Smi::FromInt(2), r0); 5039 __ AddSmiLiteral(r7, r8, Smi::FromInt(2), r0);
5139 __ StoreP(r8, FieldMemOperand(r7, FixedArray::kLengthOffset), r0); 5040 __ StoreP(r7, FieldMemOperand(r6, FixedArray::kLengthOffset), r0);
5140 __ StoreP(cp, FieldMemOperand(r7, FixedArray::kHeaderSize + 0 * kPointerSize), 5041 __ StoreP(cp, FieldMemOperand(r6, FixedArray::kHeaderSize + 0 * kPointerSize),
5141 r0); 5042 r0);
5142 __ SmiToPtrArrayOffset(r8, r9); 5043 __ SmiToPtrArrayOffset(r7, r8);
5143 __ add(r8, r8, r7); 5044 __ AddP(r7, r7, r6);
5144 __ addi(r8, r8, Operand(kParameterMapHeaderSize)); 5045 __ AddP(r7, r7, Operand(kParameterMapHeaderSize));
5145 __ StoreP(r8, FieldMemOperand(r7, FixedArray::kHeaderSize + 1 * kPointerSize), 5046 __ StoreP(r7, FieldMemOperand(r6, FixedArray::kHeaderSize + 1 * kPointerSize),
5146 r0); 5047 r0);
5147 5048
5148 // Copy the parameter slots and the holes in the arguments. 5049 // Copy the parameter slots and the holes in the arguments.
5149 // We need to fill in mapped_parameter_count slots. They index the context, 5050 // We need to fill in mapped_parameter_count slots. They index the context,
5150 // where parameters are stored in reverse order, at 5051 // where parameters are stored in reverse order, at
5151 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 5052 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
5152 // The mapped parameter thus need to get indices 5053 // The mapped parameter thus need to get indices
5153 // MIN_CONTEXT_SLOTS+parameter_count-1 .. 5054 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
5154 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 5055 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
5155 // We loop from right to left. 5056 // We loop from right to left.
5156 Label parameters_loop; 5057 Label parameters_loop;
5157 __ mr(r8, r9); 5058 __ LoadRR(r7, r8);
5158 __ AddSmiLiteral(r11, r5, Smi::FromInt(Context::MIN_CONTEXT_SLOTS), r0); 5059 __ AddSmiLiteral(r1, r4, Smi::FromInt(Context::MIN_CONTEXT_SLOTS), r0);
5159 __ sub(r11, r11, r9); 5060 __ SubP(r1, r1, r8);
5160 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 5061 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
5161 __ SmiToPtrArrayOffset(r4, r8); 5062 __ SmiToPtrArrayOffset(r3, r7);
5162 __ add(r4, r4, r7); 5063 __ AddP(r3, r3, r6);
5163 __ addi(r4, r4, Operand(kParameterMapHeaderSize)); 5064 __ AddP(r3, r3, Operand(kParameterMapHeaderSize));
5164 5065
5165 // r4 = address of backing store (tagged) 5066 // r3 = address of backing store (tagged)
5166 // r7 = address of parameter map (tagged) 5067 // r6 = address of parameter map (tagged)
5167 // r8 = temporary scratch (a.o., for address calculation) 5068 // r7 = temporary scratch (a.o., for address calculation)
5168 // r10 = temporary scratch (a.o., for address calculation) 5069 // r9 = temporary scratch (a.o., for address calculation)
5169 // ip = the hole value 5070 // ip = the hole value
5170 __ SmiUntag(r8); 5071 __ SmiUntag(r7);
5171 __ mtctr(r8); 5072 __ push(r4);
5172 __ ShiftLeftImm(r8, r8, Operand(kPointerSizeLog2)); 5073 __ LoadRR(r4, r7);
5173 __ add(r10, r4, r8); 5074 __ ShiftLeftP(r7, r7, Operand(kPointerSizeLog2));
5174 __ add(r8, r7, r8); 5075 __ AddP(r9, r3, r7);
5175 __ addi(r10, r10, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 5076 __ AddP(r7, r6, r7);
5176 __ addi(r8, r8, Operand(kParameterMapHeaderSize - kHeapObjectTag)); 5077 __ AddP(r9, r9, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
5078 __ AddP(r7, r7, Operand(kParameterMapHeaderSize - kHeapObjectTag));
5177 5079
5178 __ bind(&parameters_loop); 5080 __ bind(&parameters_loop);
5179 __ StorePU(r11, MemOperand(r8, -kPointerSize)); 5081 __ StoreP(r1, MemOperand(r7, -kPointerSize));
5180 __ StorePU(ip, MemOperand(r10, -kPointerSize)); 5082 __ lay(r7, MemOperand(r7, -kPointerSize));
5181 __ AddSmiLiteral(r11, r11, Smi::FromInt(1), r0); 5083 __ StoreP(ip, MemOperand(r9, -kPointerSize));
5182 __ bdnz(&parameters_loop); 5084 __ lay(r9, MemOperand(r9, -kPointerSize));
5085 __ AddSmiLiteral(r1, r1, Smi::FromInt(1), r0);
5086 __ BranchOnCount(r4, &parameters_loop);
5087 __ pop(r4);
5183 5088
5184 // Restore r8 = argument count (tagged). 5089 // Restore r7 = argument count (tagged).
5185 __ LoadP(r8, FieldMemOperand(r3, JSSloppyArgumentsObject::kLengthOffset)); 5090 __ LoadP(r7, FieldMemOperand(r2, JSSloppyArgumentsObject::kLengthOffset));
5186 5091
5187 __ bind(&skip_parameter_map); 5092 __ bind(&skip_parameter_map);
5188 // r3 = address of new object (tagged) 5093 // r2 = address of new object (tagged)
5189 // r4 = address of backing store (tagged) 5094 // r3 = address of backing store (tagged)
5190 // r8 = argument count (tagged) 5095 // r7 = argument count (tagged)
5191 // r9 = mapped parameter count (tagged) 5096 // r8 = mapped parameter count (tagged)
5192 // r11 = scratch 5097 // r1 = scratch
5193 // Copy arguments header and remaining slots (if there are any). 5098 // Copy arguments header and remaining slots (if there are any).
5194 __ LoadRoot(r11, Heap::kFixedArrayMapRootIndex); 5099 __ LoadRoot(r1, Heap::kFixedArrayMapRootIndex);
5195 __ StoreP(r11, FieldMemOperand(r4, FixedArray::kMapOffset), r0); 5100 __ StoreP(r1, FieldMemOperand(r3, FixedArray::kMapOffset), r0);
5196 __ StoreP(r8, FieldMemOperand(r4, FixedArray::kLengthOffset), r0); 5101 __ StoreP(r7, FieldMemOperand(r3, FixedArray::kLengthOffset), r0);
5197 __ sub(r11, r8, r9, LeaveOE, SetRC); 5102 __ SubP(r1, r7, r8);
5198 __ Ret(eq, cr0); 5103 __ Ret(eq);
5199 5104
5200 Label arguments_loop; 5105 Label arguments_loop;
5201 __ SmiUntag(r11); 5106 __ SmiUntag(r1);
5202 __ mtctr(r11); 5107 __ LoadRR(r4, r1);
5203 5108
5204 __ SmiToPtrArrayOffset(r0, r9); 5109 __ SmiToPtrArrayOffset(r0, r8);
5205 __ sub(r6, r6, r0); 5110 __ SubP(r5, r5, r0);
5206 __ add(r11, r4, r0); 5111 __ AddP(r1, r3, r0);
5207 __ addi(r11, r11, 5112 __ AddP(r1, r1,
5208 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); 5113 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
5209 5114
5210 __ bind(&arguments_loop); 5115 __ bind(&arguments_loop);
5211 __ LoadPU(r7, MemOperand(r6, -kPointerSize)); 5116 __ LoadP(r6, MemOperand(r5, -kPointerSize));
5212 __ StorePU(r7, MemOperand(r11, kPointerSize)); 5117 __ lay(r5, MemOperand(r5, -kPointerSize));
5213 __ bdnz(&arguments_loop); 5118 __ StoreP(r6, MemOperand(r1, kPointerSize));
5119 __ la(r1, MemOperand(r1, kPointerSize));
5120 __ BranchOnCount(r4, &arguments_loop);
5214 5121
5215 // Return. 5122 // Return.
5216 __ Ret(); 5123 __ Ret();
5217 5124
5218 // Do the runtime call to allocate the arguments object. 5125 // Do the runtime call to allocate the arguments object.
5219 // r8 = argument count (tagged) 5126 // r7 = argument count (tagged)
5220 __ bind(&runtime); 5127 __ bind(&runtime);
5221 __ Push(r4, r6, r8); 5128 __ Push(r3, r5, r7);
5222 __ TailCallRuntime(Runtime::kNewSloppyArguments); 5129 __ TailCallRuntime(Runtime::kNewSloppyArguments);
5223 } 5130 }
5224 5131
5225 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { 5132 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
5226 // ----------- S t a t e ------------- 5133 // ----------- S t a t e -------------
5227 // -- r4 : function 5134 // -- r3 : function
5228 // -- cp : context 5135 // -- cp : context
5229 // -- fp : frame pointer 5136 // -- fp : frame pointer
5230 // -- lr : return address 5137 // -- lr : return address
5231 // ----------------------------------- 5138 // -----------------------------------
5232 __ AssertFunction(r4); 5139 __ AssertFunction(r3);
5233 5140
5234 // For Ignition we need to skip all possible handler/stub frames until 5141 // For Ignition we need to skip all possible handler/stub frames until
5235 // we reach the JavaScript frame for the function (similar to what the 5142 // we reach the JavaScript frame for the function (similar to what the
5236 // runtime fallback implementation does). So make r5 point to that 5143 // runtime fallback implementation does). So make r4 point to that
5237 // JavaScript frame. 5144 // JavaScript frame.
5238 { 5145 {
5239 Label loop, loop_entry; 5146 Label loop, loop_entry;
5240 __ mr(r5, fp); 5147 __ LoadRR(r4, fp);
5241 __ b(&loop_entry); 5148 __ b(&loop_entry);
5242 __ bind(&loop); 5149 __ bind(&loop);
5243 __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 5150 __ LoadP(r4, MemOperand(r4, StandardFrameConstants::kCallerFPOffset));
5244 __ bind(&loop_entry); 5151 __ bind(&loop_entry);
5245 __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kMarkerOffset)); 5152 __ LoadP(ip, MemOperand(r4, StandardFrameConstants::kMarkerOffset));
5246 __ cmp(ip, r4); 5153 __ CmpP(ip, r3);
5247 __ bne(&loop); 5154 __ bne(&loop);
5248 } 5155 }
5249 5156
5250 // Check if we have an arguments adaptor frame below the function frame. 5157 // Check if we have an arguments adaptor frame below the function frame.
5251 Label arguments_adaptor, arguments_done; 5158 Label arguments_adaptor, arguments_done;
5252 __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kCallerFPOffset)); 5159 __ LoadP(r5, MemOperand(r4, StandardFrameConstants::kCallerFPOffset));
5253 __ LoadP(ip, MemOperand(r6, StandardFrameConstants::kContextOffset)); 5160 __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kContextOffset));
5254 __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); 5161 __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
5255 __ beq(&arguments_adaptor); 5162 __ beq(&arguments_adaptor);
5256 { 5163 {
5257 __ LoadP(r4, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 5164 __ LoadP(r3, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
5258 __ LoadWordArith( 5165 __ LoadW(r2, FieldMemOperand(
5259 r3, 5166 r3, SharedFunctionInfo::kFormalParameterCountOffset));
5260 FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset)); 5167 #if V8_TARGET_ARCH_S390X
5261 #if V8_TARGET_ARCH_PPC64 5168 __ SmiTag(r2);
5262 __ SmiTag(r3);
5263 #endif 5169 #endif
5264 __ SmiToPtrArrayOffset(r9, r3); 5170 __ SmiToPtrArrayOffset(r8, r2);
5265 __ add(r5, r5, r9); 5171 __ AddP(r4, r4, r8);
5266 } 5172 }
5267 __ b(&arguments_done); 5173 __ b(&arguments_done);
5268 __ bind(&arguments_adaptor); 5174 __ bind(&arguments_adaptor);
5269 { 5175 {
5270 __ LoadP(r3, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset)); 5176 __ LoadP(r2, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
5271 __ SmiToPtrArrayOffset(r9, r3); 5177 __ SmiToPtrArrayOffset(r8, r2);
5272 __ add(r5, r6, r9); 5178 __ AddP(r4, r5, r8);
5273 } 5179 }
5274 __ bind(&arguments_done); 5180 __ bind(&arguments_done);
5275 __ addi(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset)); 5181 __ AddP(r4, r4, Operand(StandardFrameConstants::kCallerSPOffset));
5276 5182
5277 // ----------- S t a t e ------------- 5183 // ----------- S t a t e -------------
5278 // -- cp : context 5184 // -- cp : context
5279 // -- r3 : number of rest parameters (tagged) 5185 // -- r2 : number of rest parameters (tagged)
5280 // -- r5 : pointer just past first rest parameters 5186 // -- r4 : pointer just past first rest parameters
5281 // -- r9 : size of rest parameters 5187 // -- r8 : size of rest parameters
5282 // -- lr : return address 5188 // -- lr : return address
5283 // ----------------------------------- 5189 // -----------------------------------
5284 5190
5285 // Allocate space for the strict arguments object plus the backing store. 5191 // Allocate space for the strict arguments object plus the backing store.
5286 Label allocate, done_allocate; 5192 Label allocate, done_allocate;
5287 __ mov(r4, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); 5193 __ mov(r3, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
5288 __ add(r4, r4, r9); 5194 __ AddP(r3, r3, r8);
5289 __ Allocate(r4, r6, r7, r8, &allocate, TAG_OBJECT); 5195 __ Allocate(r3, r5, r6, r7, &allocate, TAG_OBJECT);
5290 __ bind(&done_allocate); 5196 __ bind(&done_allocate);
5291 5197
5292 // Setup the elements array in r6. 5198 // Setup the elements array in r5.
5293 __ LoadRoot(r4, Heap::kFixedArrayMapRootIndex); 5199 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
5294 __ StoreP(r4, FieldMemOperand(r6, FixedArray::kMapOffset), r0); 5200 __ StoreP(r3, FieldMemOperand(r5, FixedArray::kMapOffset), r0);
5295 __ StoreP(r3, FieldMemOperand(r6, FixedArray::kLengthOffset), r0); 5201 __ StoreP(r2, FieldMemOperand(r5, FixedArray::kLengthOffset), r0);
5296 __ addi(r7, r6, 5202 __ AddP(r6, r5,
5297 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize)); 5203 Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
5298 { 5204 {
5299 Label loop, done_loop; 5205 Label loop, done_loop;
5300 __ SmiUntag(r0, r3, SetRC); 5206 __ SmiUntag(r1, r2);
5301 __ beq(&done_loop, cr0); 5207 __ LoadAndTestP(r1, r1);
5302 __ mtctr(r0); 5208 __ beq(&done_loop);
5303 __ bind(&loop); 5209 __ bind(&loop);
5304 __ LoadPU(ip, MemOperand(r5, -kPointerSize)); 5210 __ lay(r4, MemOperand(r4, -kPointerSize));
5305 __ StorePU(ip, MemOperand(r7, kPointerSize)); 5211 __ LoadP(ip, MemOperand(r4));
5306 __ bdnz(&loop); 5212 __ la(r6, MemOperand(r6, kPointerSize));
5213 __ StoreP(ip, MemOperand(r6));
5214 __ BranchOnCount(r1, &loop);
5307 __ bind(&done_loop); 5215 __ bind(&done_loop);
5308 __ addi(r7, r7, Operand(kPointerSize)); 5216 __ AddP(r6, r6, Operand(kPointerSize));
5309 } 5217 }
5310 5218
5311 // Setup the rest parameter array in r7. 5219 // Setup the rest parameter array in r6.
5312 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, r4); 5220 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, r3);
5313 __ StoreP(r4, MemOperand(r7, JSStrictArgumentsObject::kMapOffset)); 5221 __ StoreP(r3, MemOperand(r6, JSStrictArgumentsObject::kMapOffset));
5314 __ LoadRoot(r4, Heap::kEmptyFixedArrayRootIndex); 5222 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
5315 __ StoreP(r4, MemOperand(r7, JSStrictArgumentsObject::kPropertiesOffset)); 5223 __ StoreP(r3, MemOperand(r6, JSStrictArgumentsObject::kPropertiesOffset));
5316 __ StoreP(r6, MemOperand(r7, JSStrictArgumentsObject::kElementsOffset)); 5224 __ StoreP(r5, MemOperand(r6, JSStrictArgumentsObject::kElementsOffset));
5317 __ StoreP(r3, MemOperand(r7, JSStrictArgumentsObject::kLengthOffset)); 5225 __ StoreP(r2, MemOperand(r6, JSStrictArgumentsObject::kLengthOffset));
5318 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); 5226 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
5319 __ addi(r3, r7, Operand(kHeapObjectTag)); 5227 __ AddP(r2, r6, Operand(kHeapObjectTag));
5320 __ Ret(); 5228 __ Ret();
5321 5229
5322 // Fall back to %AllocateInNewSpace. 5230 // Fall back to %AllocateInNewSpace.
5323 __ bind(&allocate); 5231 __ bind(&allocate);
5324 { 5232 {
5325 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 5233 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
5326 __ SmiTag(r4); 5234 __ SmiTag(r3);
5327 __ Push(r3, r5, r4); 5235 __ Push(r2, r4, r3);
5328 __ CallRuntime(Runtime::kAllocateInNewSpace); 5236 __ CallRuntime(Runtime::kAllocateInNewSpace);
5329 __ mr(r6, r3); 5237 __ LoadRR(r5, r2);
5330 __ Pop(r3, r5); 5238 __ Pop(r2, r4);
5331 } 5239 }
5332 __ b(&done_allocate); 5240 __ b(&done_allocate);
5333 } 5241 }
5334 5242
5335 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { 5243 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
5336 Register context = cp; 5244 Register context = cp;
5337 Register result = r3; 5245 Register result = r2;
5338 Register slot = r5; 5246 Register slot = r4;
5339 5247
5340 // Go up the context chain to the script context. 5248 // Go up the context chain to the script context.
5341 for (int i = 0; i < depth(); ++i) { 5249 for (int i = 0; i < depth(); ++i) {
5342 __ LoadP(result, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 5250 __ LoadP(result, ContextMemOperand(context, Context::PREVIOUS_INDEX));
5343 context = result; 5251 context = result;
5344 } 5252 }
5345 5253
5346 // Load the PropertyCell value at the specified slot. 5254 // Load the PropertyCell value at the specified slot.
5347 __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); 5255 __ ShiftLeftP(r0, slot, Operand(kPointerSizeLog2));
5348 __ add(result, context, r0); 5256 __ AddP(result, context, r0);
5349 __ LoadP(result, ContextMemOperand(result)); 5257 __ LoadP(result, ContextMemOperand(result));
5350 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); 5258 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset));
5351 5259
5352 // If the result is not the_hole, return. Otherwise, handle in the runtime. 5260 // If the result is not the_hole, return. Otherwise, handle in the runtime.
5353 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 5261 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
5354 __ Ret(ne); 5262 Label runtime;
5263 __ beq(&runtime);
5264 __ Ret();
5265 __ bind(&runtime);
5355 5266
5356 // Fallback to runtime. 5267 // Fallback to runtime.
5357 __ SmiTag(slot); 5268 __ SmiTag(slot);
5358 __ Push(slot); 5269 __ Push(slot);
5359 __ TailCallRuntime(Runtime::kLoadGlobalViaContext); 5270 __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
5360 } 5271 }
5361 5272
5273 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) {
5274 Register value = r2;
5275 Register slot = r4;
5362 5276
5363 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { 5277 Register cell = r3;
5364 Register value = r3; 5278 Register cell_details = r5;
5365 Register slot = r5; 5279 Register cell_value = r6;
5366 5280 Register cell_value_map = r7;
5367 Register cell = r4; 5281 Register scratch = r8;
5368 Register cell_details = r6;
5369 Register cell_value = r7;
5370 Register cell_value_map = r8;
5371 Register scratch = r9;
5372 5282
5373 Register context = cp; 5283 Register context = cp;
5374 Register context_temp = cell; 5284 Register context_temp = cell;
5375 5285
5376 Label fast_heapobject_case, fast_smi_case, slow_case; 5286 Label fast_heapobject_case, fast_smi_case, slow_case;
5377 5287
5378 if (FLAG_debug_code) { 5288 if (FLAG_debug_code) {
5379 __ CompareRoot(value, Heap::kTheHoleValueRootIndex); 5289 __ CompareRoot(value, Heap::kTheHoleValueRootIndex);
5380 __ Check(ne, kUnexpectedValue); 5290 __ Check(ne, kUnexpectedValue);
5381 } 5291 }
5382 5292
5383 // Go up the context chain to the script context. 5293 // Go up the context chain to the script context.
5384 for (int i = 0; i < depth(); i++) { 5294 for (int i = 0; i < depth(); i++) {
5385 __ LoadP(context_temp, ContextMemOperand(context, Context::PREVIOUS_INDEX)); 5295 __ LoadP(context_temp, ContextMemOperand(context, Context::PREVIOUS_INDEX));
5386 context = context_temp; 5296 context = context_temp;
5387 } 5297 }
5388 5298
5389 // Load the PropertyCell at the specified slot. 5299 // Load the PropertyCell at the specified slot.
5390 __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); 5300 __ ShiftLeftP(r0, slot, Operand(kPointerSizeLog2));
5391 __ add(cell, context, r0); 5301 __ AddP(cell, context, r0);
5392 __ LoadP(cell, ContextMemOperand(cell)); 5302 __ LoadP(cell, ContextMemOperand(cell));
5393 5303
5394 // Load PropertyDetails for the cell (actually only the cell_type and kind). 5304 // Load PropertyDetails for the cell (actually only the cell_type and kind).
5395 __ LoadP(cell_details, FieldMemOperand(cell, PropertyCell::kDetailsOffset)); 5305 __ LoadP(cell_details, FieldMemOperand(cell, PropertyCell::kDetailsOffset));
5396 __ SmiUntag(cell_details); 5306 __ SmiUntag(cell_details);
5397 __ andi(cell_details, cell_details, 5307 __ AndP(cell_details, cell_details,
5398 Operand(PropertyDetails::PropertyCellTypeField::kMask | 5308 Operand(PropertyDetails::PropertyCellTypeField::kMask |
5399 PropertyDetails::KindField::kMask | 5309 PropertyDetails::KindField::kMask |
5400 PropertyDetails::kAttributesReadOnlyMask)); 5310 PropertyDetails::kAttributesReadOnlyMask));
5401 5311
5402 // Check if PropertyCell holds mutable data. 5312 // Check if PropertyCell holds mutable data.
5403 Label not_mutable_data; 5313 Label not_mutable_data;
5404 __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( 5314 __ CmpP(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode(
5405 PropertyCellType::kMutable) | 5315 PropertyCellType::kMutable) |
5406 PropertyDetails::KindField::encode(kData))); 5316 PropertyDetails::KindField::encode(kData)));
5407 __ bne(&not_mutable_data); 5317 __ bne(&not_mutable_data);
5408 __ JumpIfSmi(value, &fast_smi_case); 5318 __ JumpIfSmi(value, &fast_smi_case);
5409 5319
5410 __ bind(&fast_heapobject_case); 5320 __ bind(&fast_heapobject_case);
5411 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); 5321 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0);
5412 // RecordWriteField clobbers the value register, so we copy it before the 5322 // RecordWriteField clobbers the value register, so we copy it before the
5413 // call. 5323 // call.
5414 __ mr(r6, value); 5324 __ LoadRR(r5, value);
5415 __ RecordWriteField(cell, PropertyCell::kValueOffset, r6, scratch, 5325 __ RecordWriteField(cell, PropertyCell::kValueOffset, r5, scratch,
5416 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 5326 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
5417 OMIT_SMI_CHECK); 5327 OMIT_SMI_CHECK);
5418 __ Ret(); 5328 __ Ret();
5419 5329
5420 __ bind(&not_mutable_data); 5330 __ bind(&not_mutable_data);
5421 // Check if PropertyCell value matches the new value (relevant for Constant, 5331 // Check if PropertyCell value matches the new value (relevant for Constant,
5422 // ConstantType and Undefined cells). 5332 // ConstantType and Undefined cells).
5423 Label not_same_value; 5333 Label not_same_value;
5424 __ LoadP(cell_value, FieldMemOperand(cell, PropertyCell::kValueOffset)); 5334 __ LoadP(cell_value, FieldMemOperand(cell, PropertyCell::kValueOffset));
5425 __ cmp(cell_value, value); 5335 __ CmpP(cell_value, value);
5426 __ bne(&not_same_value); 5336 __ bne(&not_same_value);
5427 5337
5428 // Make sure the PropertyCell is not marked READ_ONLY. 5338 // Make sure the PropertyCell is not marked READ_ONLY.
5429 __ andi(r0, cell_details, Operand(PropertyDetails::kAttributesReadOnlyMask)); 5339 __ AndP(r0, cell_details, Operand(PropertyDetails::kAttributesReadOnlyMask));
5430 __ bne(&slow_case, cr0); 5340 __ bne(&slow_case);
5431 5341
5432 if (FLAG_debug_code) { 5342 if (FLAG_debug_code) {
5433 Label done; 5343 Label done;
5434 // This can only be true for Constant, ConstantType and Undefined cells, 5344 // This can only be true for Constant, ConstantType and Undefined cells,
5435 // because we never store the_hole via this stub. 5345 // because we never store the_hole via this stub.
5436 __ cmpi(cell_details, 5346 __ CmpP(cell_details,
5437 Operand(PropertyDetails::PropertyCellTypeField::encode( 5347 Operand(PropertyDetails::PropertyCellTypeField::encode(
5438 PropertyCellType::kConstant) | 5348 PropertyCellType::kConstant) |
5439 PropertyDetails::KindField::encode(kData))); 5349 PropertyDetails::KindField::encode(kData)));
5440 __ beq(&done); 5350 __ beq(&done);
5441 __ cmpi(cell_details, 5351 __ CmpP(cell_details,
5442 Operand(PropertyDetails::PropertyCellTypeField::encode( 5352 Operand(PropertyDetails::PropertyCellTypeField::encode(
5443 PropertyCellType::kConstantType) | 5353 PropertyCellType::kConstantType) |
5444 PropertyDetails::KindField::encode(kData))); 5354 PropertyDetails::KindField::encode(kData)));
5445 __ beq(&done); 5355 __ beq(&done);
5446 __ cmpi(cell_details, 5356 __ CmpP(cell_details,
5447 Operand(PropertyDetails::PropertyCellTypeField::encode( 5357 Operand(PropertyDetails::PropertyCellTypeField::encode(
5448 PropertyCellType::kUndefined) | 5358 PropertyCellType::kUndefined) |
5449 PropertyDetails::KindField::encode(kData))); 5359 PropertyDetails::KindField::encode(kData)));
5450 __ Check(eq, kUnexpectedValue); 5360 __ Check(eq, kUnexpectedValue);
5451 __ bind(&done); 5361 __ bind(&done);
5452 } 5362 }
5453 __ Ret(); 5363 __ Ret();
5454 __ bind(&not_same_value); 5364 __ bind(&not_same_value);
5455 5365
5456 // Check if PropertyCell contains data with constant type (and is not 5366 // Check if PropertyCell contains data with constant type (and is not
5457 // READ_ONLY). 5367 // READ_ONLY).
5458 __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( 5368 __ CmpP(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode(
5459 PropertyCellType::kConstantType) | 5369 PropertyCellType::kConstantType) |
5460 PropertyDetails::KindField::encode(kData))); 5370 PropertyDetails::KindField::encode(kData)));
5461 __ bne(&slow_case); 5371 __ bne(&slow_case);
5462 5372
5463 // Now either both old and new values must be smis or both must be heap 5373 // Now either both old and new values must be smis or both must be heap
5464 // objects with same map. 5374 // objects with same map.
5465 Label value_is_heap_object; 5375 Label value_is_heap_object;
5466 __ JumpIfNotSmi(value, &value_is_heap_object); 5376 __ JumpIfNotSmi(value, &value_is_heap_object);
5467 __ JumpIfNotSmi(cell_value, &slow_case); 5377 __ JumpIfNotSmi(cell_value, &slow_case);
5468 // Old and new values are smis, no need for a write barrier here. 5378 // Old and new values are smis, no need for a write barrier here.
5469 __ bind(&fast_smi_case); 5379 __ bind(&fast_smi_case);
5470 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); 5380 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0);
5471 __ Ret(); 5381 __ Ret();
5472 5382
5473 __ bind(&value_is_heap_object); 5383 __ bind(&value_is_heap_object);
5474 __ JumpIfSmi(cell_value, &slow_case); 5384 __ JumpIfSmi(cell_value, &slow_case);
5475 5385
5476 __ LoadP(cell_value_map, FieldMemOperand(cell_value, HeapObject::kMapOffset)); 5386 __ LoadP(cell_value_map, FieldMemOperand(cell_value, HeapObject::kMapOffset));
5477 __ LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); 5387 __ LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset));
5478 __ cmp(cell_value_map, scratch); 5388 __ CmpP(cell_value_map, scratch);
5479 __ beq(&fast_heapobject_case); 5389 __ beq(&fast_heapobject_case);
5480 5390
5481 // Fallback to runtime. 5391 // Fallback to runtime.
5482 __ bind(&slow_case); 5392 __ bind(&slow_case);
5483 __ SmiTag(slot); 5393 __ SmiTag(slot);
5484 __ Push(slot, value); 5394 __ Push(slot, value);
5485 __ TailCallRuntime(is_strict(language_mode()) 5395 __ TailCallRuntime(is_strict(language_mode())
5486 ? Runtime::kStoreGlobalViaContext_Strict 5396 ? Runtime::kStoreGlobalViaContext_Strict
5487 : Runtime::kStoreGlobalViaContext_Sloppy); 5397 : Runtime::kStoreGlobalViaContext_Sloppy);
5488 } 5398 }
5489 5399
5490
5491 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { 5400 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
5492 return ref0.address() - ref1.address(); 5401 return ref0.address() - ref1.address();
5493 } 5402 }
5494 5403
5495
5496 // Calls an API function. Allocates HandleScope, extracts returned value 5404 // Calls an API function. Allocates HandleScope, extracts returned value
5497 // from handle and propagates exceptions. Restores context. stack_space 5405 // from handle and propagates exceptions. Restores context. stack_space
5498 // - space to be unwound on exit (includes the call JS arguments space and 5406 // - space to be unwound on exit (includes the call JS arguments space and
5499 // the additional space allocated for the fast call). 5407 // the additional space allocated for the fast call).
5500 static void CallApiFunctionAndReturn(MacroAssembler* masm, 5408 static void CallApiFunctionAndReturn(MacroAssembler* masm,
5501 Register function_address, 5409 Register function_address,
5502 ExternalReference thunk_ref, 5410 ExternalReference thunk_ref,
5503 int stack_space, 5411 int stack_space,
5504 MemOperand* stack_space_operand, 5412 MemOperand* stack_space_operand,
5505 MemOperand return_value_operand, 5413 MemOperand return_value_operand,
5506 MemOperand* context_restore_operand) { 5414 MemOperand* context_restore_operand) {
5507 Isolate* isolate = masm->isolate(); 5415 Isolate* isolate = masm->isolate();
5508 ExternalReference next_address = 5416 ExternalReference next_address =
5509 ExternalReference::handle_scope_next_address(isolate); 5417 ExternalReference::handle_scope_next_address(isolate);
5510 const int kNextOffset = 0; 5418 const int kNextOffset = 0;
5511 const int kLimitOffset = AddressOffset( 5419 const int kLimitOffset = AddressOffset(
5512 ExternalReference::handle_scope_limit_address(isolate), next_address); 5420 ExternalReference::handle_scope_limit_address(isolate), next_address);
5513 const int kLevelOffset = AddressOffset( 5421 const int kLevelOffset = AddressOffset(
5514 ExternalReference::handle_scope_level_address(isolate), next_address); 5422 ExternalReference::handle_scope_level_address(isolate), next_address);
5515 5423
5516 // Additional parameter is the address of the actual callback. 5424 // Additional parameter is the address of the actual callback.
5517 DCHECK(function_address.is(r4) || function_address.is(r5)); 5425 DCHECK(function_address.is(r3) || function_address.is(r4));
5518 Register scratch = r6; 5426 Register scratch = r5;
5519 5427
5520 __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate))); 5428 __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate)));
5521 __ lbz(scratch, MemOperand(scratch, 0)); 5429 __ LoadlB(scratch, MemOperand(scratch, 0));
5522 __ cmpi(scratch, Operand::Zero()); 5430 __ CmpP(scratch, Operand::Zero());
5523 5431
5524 if (CpuFeatures::IsSupported(ISELECT)) { 5432 Label profiler_disabled;
5525 __ mov(scratch, Operand(thunk_ref)); 5433 Label end_profiler_check;
5526 __ isel(eq, scratch, function_address, scratch); 5434 __ beq(&profiler_disabled, Label::kNear);
5527 } else { 5435 __ mov(scratch, Operand(thunk_ref));
5528 Label profiler_disabled; 5436 __ b(&end_profiler_check, Label::kNear);
5529 Label end_profiler_check; 5437 __ bind(&profiler_disabled);
5530 __ beq(&profiler_disabled); 5438 __ LoadRR(scratch, function_address);
5531 __ mov(scratch, Operand(thunk_ref)); 5439 __ bind(&end_profiler_check);
5532 __ b(&end_profiler_check);
5533 __ bind(&profiler_disabled);
5534 __ mr(scratch, function_address);
5535 __ bind(&end_profiler_check);
5536 }
5537 5440
5538 // Allocate HandleScope in callee-save registers. 5441 // Allocate HandleScope in callee-save registers.
5539 // r17 - next_address 5442 // r9 - next_address
5540 // r14 - next_address->kNextOffset 5443 // r6 - next_address->kNextOffset
5541 // r15 - next_address->kLimitOffset 5444 // r7 - next_address->kLimitOffset
5542 // r16 - next_address->kLevelOffset 5445 // r8 - next_address->kLevelOffset
5543 __ mov(r17, Operand(next_address)); 5446 __ mov(r9, Operand(next_address));
5544 __ LoadP(r14, MemOperand(r17, kNextOffset)); 5447 __ LoadP(r6, MemOperand(r9, kNextOffset));
5545 __ LoadP(r15, MemOperand(r17, kLimitOffset)); 5448 __ LoadP(r7, MemOperand(r9, kLimitOffset));
5546 __ lwz(r16, MemOperand(r17, kLevelOffset)); 5449 __ LoadlW(r8, MemOperand(r9, kLevelOffset));
5547 __ addi(r16, r16, Operand(1)); 5450 __ AddP(r8, Operand(1));
5548 __ stw(r16, MemOperand(r17, kLevelOffset)); 5451 __ StoreW(r8, MemOperand(r9, kLevelOffset));
5549 5452
5550 if (FLAG_log_timer_events) { 5453 if (FLAG_log_timer_events) {
5551 FrameScope frame(masm, StackFrame::MANUAL); 5454 FrameScope frame(masm, StackFrame::MANUAL);
5552 __ PushSafepointRegisters(); 5455 __ PushSafepointRegisters();
5553 __ PrepareCallCFunction(1, r3); 5456 __ PrepareCallCFunction(1, r2);
5554 __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 5457 __ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
5555 __ CallCFunction(ExternalReference::log_enter_external_function(isolate), 5458 __ CallCFunction(ExternalReference::log_enter_external_function(isolate),
5556 1); 5459 1);
5557 __ PopSafepointRegisters(); 5460 __ PopSafepointRegisters();
5558 } 5461 }
5559 5462
5560 // Native call returns to the DirectCEntry stub which redirects to the 5463 // Native call returns to the DirectCEntry stub which redirects to the
5561 // return address pushed on stack (could have moved after GC). 5464 // return address pushed on stack (could have moved after GC).
5562 // DirectCEntry stub itself is generated early and never moves. 5465 // DirectCEntry stub itself is generated early and never moves.
5563 DirectCEntryStub stub(isolate); 5466 DirectCEntryStub stub(isolate);
5564 stub.GenerateCall(masm, scratch); 5467 stub.GenerateCall(masm, scratch);
5565 5468
5566 if (FLAG_log_timer_events) { 5469 if (FLAG_log_timer_events) {
5567 FrameScope frame(masm, StackFrame::MANUAL); 5470 FrameScope frame(masm, StackFrame::MANUAL);
5568 __ PushSafepointRegisters(); 5471 __ PushSafepointRegisters();
5569 __ PrepareCallCFunction(1, r3); 5472 __ PrepareCallCFunction(1, r2);
5570 __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 5473 __ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
5571 __ CallCFunction(ExternalReference::log_leave_external_function(isolate), 5474 __ CallCFunction(ExternalReference::log_leave_external_function(isolate),
5572 1); 5475 1);
5573 __ PopSafepointRegisters(); 5476 __ PopSafepointRegisters();
5574 } 5477 }
5575 5478
5576 Label promote_scheduled_exception; 5479 Label promote_scheduled_exception;
5577 Label delete_allocated_handles; 5480 Label delete_allocated_handles;
5578 Label leave_exit_frame; 5481 Label leave_exit_frame;
5579 Label return_value_loaded; 5482 Label return_value_loaded;
5580 5483
5581 // load value from ReturnValue 5484 // load value from ReturnValue
5582 __ LoadP(r3, return_value_operand); 5485 __ LoadP(r2, return_value_operand);
5583 __ bind(&return_value_loaded); 5486 __ bind(&return_value_loaded);
5584 // No more valid handles (the result handle was the last one). Restore 5487 // No more valid handles (the result handle was the last one). Restore
5585 // previous handle scope. 5488 // previous handle scope.
5586 __ StoreP(r14, MemOperand(r17, kNextOffset)); 5489 __ StoreP(r6, MemOperand(r9, kNextOffset));
5587 if (__ emit_debug_code()) { 5490 if (__ emit_debug_code()) {
5588 __ lwz(r4, MemOperand(r17, kLevelOffset)); 5491 __ LoadlW(r3, MemOperand(r9, kLevelOffset));
5589 __ cmp(r4, r16); 5492 __ CmpP(r3, r8);
5590 __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall); 5493 __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
5591 } 5494 }
5592 __ subi(r16, r16, Operand(1)); 5495 __ SubP(r8, Operand(1));
5593 __ stw(r16, MemOperand(r17, kLevelOffset)); 5496 __ StoreW(r8, MemOperand(r9, kLevelOffset));
5594 __ LoadP(r0, MemOperand(r17, kLimitOffset)); 5497 __ CmpP(r7, MemOperand(r9, kLimitOffset));
5595 __ cmp(r15, r0); 5498 __ bne(&delete_allocated_handles, Label::kNear);
5596 __ bne(&delete_allocated_handles);
5597 5499
5598 // Leave the API exit frame. 5500 // Leave the API exit frame.
5599 __ bind(&leave_exit_frame); 5501 __ bind(&leave_exit_frame);
5600 bool restore_context = context_restore_operand != NULL; 5502 bool restore_context = context_restore_operand != NULL;
5601 if (restore_context) { 5503 if (restore_context) {
5602 __ LoadP(cp, *context_restore_operand); 5504 __ LoadP(cp, *context_restore_operand);
5603 } 5505 }
5604 // LeaveExitFrame expects unwind space to be in a register. 5506 // LeaveExitFrame expects unwind space to be in a register.
5605 if (stack_space_operand != NULL) { 5507 if (stack_space_operand != NULL) {
5606 __ lwz(r14, *stack_space_operand); 5508 __ l(r6, *stack_space_operand);
5607 } else { 5509 } else {
5608 __ mov(r14, Operand(stack_space)); 5510 __ mov(r6, Operand(stack_space));
5609 } 5511 }
5610 __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL); 5512 __ LeaveExitFrame(false, r6, !restore_context, stack_space_operand != NULL);
5611 5513
5612 // Check if the function scheduled an exception. 5514 // Check if the function scheduled an exception.
5613 __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); 5515 __ mov(r7, Operand(ExternalReference::scheduled_exception_address(isolate)));
5614 __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate))); 5516 __ LoadP(r7, MemOperand(r7));
5615 __ LoadP(r15, MemOperand(r15)); 5517 __ CompareRoot(r7, Heap::kTheHoleValueRootIndex);
5616 __ cmp(r14, r15); 5518 __ bne(&promote_scheduled_exception, Label::kNear);
5617 __ bne(&promote_scheduled_exception);
5618 5519
5619 __ blr(); 5520 __ b(r14);
5620 5521
5621 // Re-throw by promoting a scheduled exception. 5522 // Re-throw by promoting a scheduled exception.
5622 __ bind(&promote_scheduled_exception); 5523 __ bind(&promote_scheduled_exception);
5623 __ TailCallRuntime(Runtime::kPromoteScheduledException); 5524 __ TailCallRuntime(Runtime::kPromoteScheduledException);
5624 5525
5625 // HandleScope limit has changed. Delete allocated extensions. 5526 // HandleScope limit has changed. Delete allocated extensions.
5626 __ bind(&delete_allocated_handles); 5527 __ bind(&delete_allocated_handles);
5627 __ StoreP(r15, MemOperand(r17, kLimitOffset)); 5528 __ StoreP(r7, MemOperand(r9, kLimitOffset));
5628 __ mr(r14, r3); 5529 __ LoadRR(r6, r2);
5629 __ PrepareCallCFunction(1, r15); 5530 __ PrepareCallCFunction(1, r7);
5630 __ mov(r3, Operand(ExternalReference::isolate_address(isolate))); 5531 __ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
5631 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), 5532 __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate),
5632 1); 5533 1);
5633 __ mr(r3, r14); 5534 __ LoadRR(r2, r6);
5634 __ b(&leave_exit_frame); 5535 __ b(&leave_exit_frame, Label::kNear);
5635 } 5536 }
5636 5537
5637 static void CallApiFunctionStubHelper(MacroAssembler* masm, 5538 static void CallApiFunctionStubHelper(MacroAssembler* masm,
5638 const ParameterCount& argc, 5539 const ParameterCount& argc,
5639 bool return_first_arg, 5540 bool return_first_arg,
5640 bool call_data_undefined, bool is_lazy) { 5541 bool call_data_undefined, bool is_lazy) {
5641 // ----------- S t a t e ------------- 5542 // ----------- S t a t e -------------
5642 // -- r3 : callee 5543 // -- r2 : callee
5643 // -- r7 : call_data 5544 // -- r6 : call_data
5644 // -- r5 : holder 5545 // -- r4 : holder
5645 // -- r4 : api_function_address 5546 // -- r3 : api_function_address
5646 // -- r6 : number of arguments if argc is a register 5547 // -- r5 : number of arguments if argc is a register
5647 // -- cp : context 5548 // -- cp : context
5648 // -- 5549 // --
5649 // -- sp[0] : last argument 5550 // -- sp[0] : last argument
5650 // -- ... 5551 // -- ...
5651 // -- sp[(argc - 1)* 4] : first argument 5552 // -- sp[(argc - 1)* 4] : first argument
5652 // -- sp[argc * 4] : receiver 5553 // -- sp[argc * 4] : receiver
5653 // ----------------------------------- 5554 // -----------------------------------
5654 5555
5655 Register callee = r3; 5556 Register callee = r2;
5656 Register call_data = r7; 5557 Register call_data = r6;
5657 Register holder = r5; 5558 Register holder = r4;
5658 Register api_function_address = r4; 5559 Register api_function_address = r3;
5659 Register context = cp; 5560 Register context = cp;
5660 5561
5661 typedef FunctionCallbackArguments FCA; 5562 typedef FunctionCallbackArguments FCA;
5662 5563
5663 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 5564 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
5664 STATIC_ASSERT(FCA::kCalleeIndex == 5); 5565 STATIC_ASSERT(FCA::kCalleeIndex == 5);
5665 STATIC_ASSERT(FCA::kDataIndex == 4); 5566 STATIC_ASSERT(FCA::kDataIndex == 4);
5666 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 5567 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
5667 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 5568 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
5668 STATIC_ASSERT(FCA::kIsolateIndex == 1); 5569 STATIC_ASSERT(FCA::kIsolateIndex == 1);
5669 STATIC_ASSERT(FCA::kHolderIndex == 0); 5570 STATIC_ASSERT(FCA::kHolderIndex == 0);
5670 STATIC_ASSERT(FCA::kArgsLength == 7); 5571 STATIC_ASSERT(FCA::kArgsLength == 7);
5671 5572
5672 DCHECK(argc.is_immediate() || r3.is(argc.reg())); 5573 DCHECK(argc.is_immediate() || r2.is(argc.reg()));
5673 5574
5674 // context save 5575 // context save
5675 __ push(context); 5576 __ push(context);
5676 if (!is_lazy) { 5577 if (!is_lazy) {
5677 // load context from callee 5578 // load context from callee
5678 __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset)); 5579 __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset));
5679 } 5580 }
5680 5581
5681 // callee 5582 // callee
5682 __ push(callee); 5583 __ push(callee);
5683 5584
5684 // call data 5585 // call data
5685 __ push(call_data); 5586 __ push(call_data);
5686 5587
5687 Register scratch = call_data; 5588 Register scratch = call_data;
5688 if (!call_data_undefined) { 5589 if (!call_data_undefined) {
5689 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 5590 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
5690 } 5591 }
5691 // return value 5592 // return value
5692 __ push(scratch); 5593 __ push(scratch);
5693 // return value default 5594 // return value default
5694 __ push(scratch); 5595 __ push(scratch);
5695 // isolate 5596 // isolate
5696 __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate()))); 5597 __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate())));
5697 __ push(scratch); 5598 __ push(scratch);
5698 // holder 5599 // holder
5699 __ push(holder); 5600 __ push(holder);
5700 5601
5701 // Prepare arguments. 5602 // Prepare arguments.
5702 __ mr(scratch, sp); 5603 __ LoadRR(scratch, sp);
5703 5604
5704 // Allocate the v8::Arguments structure in the arguments' space since 5605 // Allocate the v8::Arguments structure in the arguments' space since
5705 // it's not controlled by GC. 5606 // it's not controlled by GC.
5706 // PPC LINUX ABI: 5607 // S390 LINUX ABI:
5707 // 5608 //
5708 // Create 5 extra slots on stack: 5609 // Create 5 extra slots on stack:
5709 // [0] space for DirectCEntryStub's LR save 5610 // [0] space for DirectCEntryStub's LR save
5710 // [1-4] FunctionCallbackInfo 5611 // [1-4] FunctionCallbackInfo
5711 const int kApiStackSpace = 5; 5612 const int kApiStackSpace = 5;
5712 const int kFunctionCallbackInfoOffset = 5613 const int kFunctionCallbackInfoOffset =
5713 (kStackFrameExtraParamSlot + 1) * kPointerSize; 5614 (kStackFrameExtraParamSlot + 1) * kPointerSize;
5714 5615
5715 FrameScope frame_scope(masm, StackFrame::MANUAL); 5616 FrameScope frame_scope(masm, StackFrame::MANUAL);
5716 __ EnterExitFrame(false, kApiStackSpace); 5617 __ EnterExitFrame(false, kApiStackSpace);
5717 5618
5718 DCHECK(!api_function_address.is(r3) && !scratch.is(r3)); 5619 DCHECK(!api_function_address.is(r2) && !scratch.is(r2));
5719 // r3 = FunctionCallbackInfo& 5620 // r2 = FunctionCallbackInfo&
5720 // Arguments is after the return address. 5621 // Arguments is after the return address.
5721 __ addi(r3, sp, Operand(kFunctionCallbackInfoOffset)); 5622 __ AddP(r2, sp, Operand(kFunctionCallbackInfoOffset));
5722 // FunctionCallbackInfo::implicit_args_ 5623 // FunctionCallbackInfo::implicit_args_
5723 __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize)); 5624 __ StoreP(scratch, MemOperand(r2, 0 * kPointerSize));
5724 if (argc.is_immediate()) { 5625 if (argc.is_immediate()) {
5725 // FunctionCallbackInfo::values_ 5626 // FunctionCallbackInfo::values_
5726 __ addi(ip, scratch, 5627 __ AddP(ip, scratch,
5727 Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize)); 5628 Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize));
5728 __ StoreP(ip, MemOperand(r3, 1 * kPointerSize)); 5629 __ StoreP(ip, MemOperand(r2, 1 * kPointerSize));
5729 // FunctionCallbackInfo::length_ = argc 5630 // FunctionCallbackInfo::length_ = argc
5730 __ li(ip, Operand(argc.immediate())); 5631 __ LoadImmP(ip, Operand(argc.immediate()));
5731 __ stw(ip, MemOperand(r3, 2 * kPointerSize)); 5632 __ StoreW(ip, MemOperand(r2, 2 * kPointerSize));
5732 // FunctionCallbackInfo::is_construct_call_ = 0 5633 // FunctionCallbackInfo::is_construct_call_ = 0
5733 __ li(ip, Operand::Zero()); 5634 __ LoadImmP(ip, Operand::Zero());
5734 __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize)); 5635 __ StoreW(ip, MemOperand(r2, 2 * kPointerSize + kIntSize));
5735 } else { 5636 } else {
5736 __ ShiftLeftImm(ip, argc.reg(), Operand(kPointerSizeLog2)); 5637 __ ShiftLeftP(ip, argc.reg(), Operand(kPointerSizeLog2));
5737 __ addi(ip, ip, Operand((FCA::kArgsLength - 1) * kPointerSize)); 5638 __ AddP(ip, ip, Operand((FCA::kArgsLength - 1) * kPointerSize));
5738 // FunctionCallbackInfo::values_ 5639 // FunctionCallbackInfo::values_
5739 __ add(r0, scratch, ip); 5640 __ AddP(r0, scratch, ip);
5740 __ StoreP(r0, MemOperand(r3, 1 * kPointerSize)); 5641 __ StoreP(r0, MemOperand(r2, 1 * kPointerSize));
5741 // FunctionCallbackInfo::length_ = argc 5642 // FunctionCallbackInfo::length_ = argc
5742 __ stw(argc.reg(), MemOperand(r3, 2 * kPointerSize)); 5643 __ StoreW(argc.reg(), MemOperand(r2, 2 * kPointerSize));
5743 // FunctionCallbackInfo::is_construct_call_ 5644 // FunctionCallbackInfo::is_construct_call_
5744 __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize)); 5645 __ StoreW(ip, MemOperand(r2, 2 * kPointerSize + kIntSize));
5745 } 5646 }
5746 5647
5747 ExternalReference thunk_ref = 5648 ExternalReference thunk_ref =
5748 ExternalReference::invoke_function_callback(masm->isolate()); 5649 ExternalReference::invoke_function_callback(masm->isolate());
5749 5650
5750 AllowExternalCallThatCantCauseGC scope(masm); 5651 AllowExternalCallThatCantCauseGC scope(masm);
5751 MemOperand context_restore_operand( 5652 MemOperand context_restore_operand(
5752 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); 5653 fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
5753 // Stores return the first js argument 5654 // Stores return the first js argument
5754 int return_value_offset = 0; 5655 int return_value_offset = 0;
5755 if (return_first_arg) { 5656 if (return_first_arg) {
5756 return_value_offset = 2 + FCA::kArgsLength; 5657 return_value_offset = 2 + FCA::kArgsLength;
5757 } else { 5658 } else {
5758 return_value_offset = 2 + FCA::kReturnValueOffset; 5659 return_value_offset = 2 + FCA::kReturnValueOffset;
5759 } 5660 }
5760 MemOperand return_value_operand(fp, return_value_offset * kPointerSize); 5661 MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
5761 int stack_space = 0; 5662 int stack_space = 0;
5762 MemOperand is_construct_call_operand = 5663 MemOperand is_construct_call_operand =
5763 MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize); 5664 MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize);
5764 MemOperand* stack_space_operand = &is_construct_call_operand; 5665 MemOperand* stack_space_operand = &is_construct_call_operand;
5765 if (argc.is_immediate()) { 5666 if (argc.is_immediate()) {
5766 stack_space = argc.immediate() + FCA::kArgsLength + 1; 5667 stack_space = argc.immediate() + FCA::kArgsLength + 1;
5767 stack_space_operand = NULL; 5668 stack_space_operand = NULL;
5768 } 5669 }
5769 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space, 5670 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
5770 stack_space_operand, return_value_operand, 5671 stack_space_operand, return_value_operand,
5771 &context_restore_operand); 5672 &context_restore_operand);
5772 } 5673 }
5773 5674
5774
5775 void CallApiFunctionStub::Generate(MacroAssembler* masm) { 5675 void CallApiFunctionStub::Generate(MacroAssembler* masm) {
5776 bool call_data_undefined = this->call_data_undefined(); 5676 bool call_data_undefined = this->call_data_undefined();
5777 CallApiFunctionStubHelper(masm, ParameterCount(r6), false, 5677 CallApiFunctionStubHelper(masm, ParameterCount(r6), false,
5778 call_data_undefined, false); 5678 call_data_undefined, false);
5779 } 5679 }
5780 5680
5781
5782 void CallApiAccessorStub::Generate(MacroAssembler* masm) { 5681 void CallApiAccessorStub::Generate(MacroAssembler* masm) {
5783 bool is_store = this->is_store(); 5682 bool is_store = this->is_store();
5784 int argc = this->argc(); 5683 int argc = this->argc();
5785 bool call_data_undefined = this->call_data_undefined(); 5684 bool call_data_undefined = this->call_data_undefined();
5786 bool is_lazy = this->is_lazy(); 5685 bool is_lazy = this->is_lazy();
5787 CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store, 5686 CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
5788 call_data_undefined, is_lazy); 5687 call_data_undefined, is_lazy);
5789 } 5688 }
5790 5689
5791
5792 void CallApiGetterStub::Generate(MacroAssembler* masm) { 5690 void CallApiGetterStub::Generate(MacroAssembler* masm) {
5793 // ----------- S t a t e ------------- 5691 // ----------- S t a t e -------------
5794 // -- sp[0] : name 5692 // -- sp[0] : name
5795 // -- sp[4 .. (4 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_ 5693 // -- sp[4 .. (4 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_
5796 // -- ... 5694 // -- ...
5797 // -- r5 : api_function_address 5695 // -- r4 : api_function_address
5798 // ----------------------------------- 5696 // -----------------------------------
5799 5697
5800 Register api_function_address = ApiGetterDescriptor::function_address(); 5698 Register api_function_address = ApiGetterDescriptor::function_address();
5801 int arg0Slot = 0; 5699 int arg0Slot = 0;
5802 int accessorInfoSlot = 0; 5700 int accessorInfoSlot = 0;
5803 int apiStackSpace = 0; 5701 int apiStackSpace = 0;
5804 DCHECK(api_function_address.is(r5)); 5702 DCHECK(api_function_address.is(r4));
5805 5703
5806 // v8::PropertyCallbackInfo::args_ array and name handle. 5704 // v8::PropertyCallbackInfo::args_ array and name handle.
5807 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; 5705 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
5808 5706
5809 // Load address of v8::PropertyAccessorInfo::args_ array and name handle. 5707 // Load address of v8::PropertyAccessorInfo::args_ array and name handle.
5810 __ mr(r3, sp); // r3 = Handle<Name> 5708 __ LoadRR(r2, sp); // r2 = Handle<Name>
5811 __ addi(r4, r3, Operand(1 * kPointerSize)); // r4 = v8::PCI::args_ 5709 __ AddP(r3, r2, Operand(1 * kPointerSize)); // r3 = v8::PCI::args_
5812 5710
5813 // If ABI passes Handles (pointer-sized struct) in a register: 5711 // If ABI passes Handles (pointer-sized struct) in a register:
5814 // 5712 //
5815 // Create 2 extra slots on stack: 5713 // Create 2 extra slots on stack:
5816 // [0] space for DirectCEntryStub's LR save 5714 // [0] space for DirectCEntryStub's LR save
5817 // [1] AccessorInfo& 5715 // [1] AccessorInfo&
5818 // 5716 //
5819 // Otherwise: 5717 // Otherwise:
5820 // 5718 //
5821 // Create 3 extra slots on stack: 5719 // Create 3 extra slots on stack:
5822 // [0] space for DirectCEntryStub's LR save 5720 // [0] space for DirectCEntryStub's LR save
5823 // [1] copy of Handle (first arg) 5721 // [1] copy of Handle (first arg)
5824 // [2] AccessorInfo& 5722 // [2] AccessorInfo&
5825 if (ABI_PASSES_HANDLES_IN_REGS) { 5723 if (ABI_PASSES_HANDLES_IN_REGS) {
5826 accessorInfoSlot = kStackFrameExtraParamSlot + 1; 5724 accessorInfoSlot = kStackFrameExtraParamSlot + 1;
5827 apiStackSpace = 2; 5725 apiStackSpace = 2;
5828 } else { 5726 } else {
5829 arg0Slot = kStackFrameExtraParamSlot + 1; 5727 arg0Slot = kStackFrameExtraParamSlot + 1;
5830 accessorInfoSlot = arg0Slot + 1; 5728 accessorInfoSlot = arg0Slot + 1;
5831 apiStackSpace = 3; 5729 apiStackSpace = 3;
5832 } 5730 }
5833 5731
5834 FrameScope frame_scope(masm, StackFrame::MANUAL); 5732 FrameScope frame_scope(masm, StackFrame::MANUAL);
5835 __ EnterExitFrame(false, apiStackSpace); 5733 __ EnterExitFrame(false, apiStackSpace);
5836 5734
5837 if (!ABI_PASSES_HANDLES_IN_REGS) { 5735 if (!ABI_PASSES_HANDLES_IN_REGS) {
5838 // pass 1st arg by reference 5736 // pass 1st arg by reference
5839 __ StoreP(r3, MemOperand(sp, arg0Slot * kPointerSize)); 5737 __ StoreP(r2, MemOperand(sp, arg0Slot * kPointerSize));
5840 __ addi(r3, sp, Operand(arg0Slot * kPointerSize)); 5738 __ AddP(r2, sp, Operand(arg0Slot * kPointerSize));
5841 } 5739 }
5842 5740
5843 // Create v8::PropertyCallbackInfo object on the stack and initialize 5741 // Create v8::PropertyCallbackInfo object on the stack and initialize
5844 // it's args_ field. 5742 // it's args_ field.
5845 __ StoreP(r4, MemOperand(sp, accessorInfoSlot * kPointerSize)); 5743 __ StoreP(r3, MemOperand(sp, accessorInfoSlot * kPointerSize));
5846 __ addi(r4, sp, Operand(accessorInfoSlot * kPointerSize)); 5744 __ AddP(r3, sp, Operand(accessorInfoSlot * kPointerSize));
5847 // r4 = v8::PropertyCallbackInfo& 5745 // r3 = v8::PropertyCallbackInfo&
5848 5746
5849 ExternalReference thunk_ref = 5747 ExternalReference thunk_ref =
5850 ExternalReference::invoke_accessor_getter_callback(isolate()); 5748 ExternalReference::invoke_accessor_getter_callback(isolate());
5851 5749
5852 // +3 is to skip prolog, return address and name handle. 5750 // +3 is to skip prolog, return address and name handle.
5853 MemOperand return_value_operand( 5751 MemOperand return_value_operand(
5854 fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize); 5752 fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
5855 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, 5753 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
5856 kStackUnwindSpace, NULL, return_value_operand, NULL); 5754 kStackUnwindSpace, NULL, return_value_operand, NULL);
5857 } 5755 }
5858 5756
5757 #undef __
5859 5758
5860 #undef __
5861 } // namespace internal 5759 } // namespace internal
5862 } // namespace v8 5760 } // namespace v8
5863 5761
5864 #endif // V8_TARGET_ARCH_PPC 5762 #endif // V8_TARGET_ARCH_S390
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698