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

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

Issue 422063005: Contribution of PowerPC port. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 //
3 // Copyright IBM Corp. 2012, 2013. All rights reserved.
4 //
2 // Use of this source code is governed by a BSD-style license that can be 5 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 6 // found in the LICENSE file.
4 7
5 #include "src/v8.h" 8 #include "src/v8.h"
6 9
7 #if V8_TARGET_ARCH_ARM 10 #if V8_TARGET_ARCH_PPC
8 11
9 #include "src/bootstrapper.h" 12 #include "src/bootstrapper.h"
10 #include "src/code-stubs.h" 13 #include "src/code-stubs.h"
11 #include "src/regexp-macro-assembler.h" 14 #include "src/regexp-macro-assembler.h"
12 #include "src/stub-cache.h" 15 #include "src/stub-cache.h"
13 16
17 #include "src/ppc/regexp-macro-assembler-ppc.h"
18
14 namespace v8 { 19 namespace v8 {
15 namespace internal { 20 namespace internal {
16 21
17 22
18 void FastNewClosureStub::InitializeInterfaceDescriptor( 23 void FastNewClosureStub::InitializeInterfaceDescriptor(
19 CodeStubInterfaceDescriptor* descriptor) { 24 CodeStubInterfaceDescriptor* descriptor) {
20 Register registers[] = { cp, r2 }; 25 Register registers[] = { cp, r5 };
21 descriptor->Initialize( 26 descriptor->Initialize(
22 ARRAY_SIZE(registers), registers, 27 ARRAY_SIZE(registers), registers,
23 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); 28 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
24 } 29 }
25 30
26 31
27 void FastNewContextStub::InitializeInterfaceDescriptor( 32 void FastNewContextStub::InitializeInterfaceDescriptor(
28 CodeStubInterfaceDescriptor* descriptor) { 33 CodeStubInterfaceDescriptor* descriptor) {
29 Register registers[] = { cp, r1 }; 34 Register registers[] = { cp, r4 };
30 descriptor->Initialize(ARRAY_SIZE(registers), registers); 35 descriptor->Initialize(ARRAY_SIZE(registers), registers);
31 } 36 }
32 37
33 38
34 void ToNumberStub::InitializeInterfaceDescriptor( 39 void ToNumberStub::InitializeInterfaceDescriptor(
35 CodeStubInterfaceDescriptor* descriptor) { 40 CodeStubInterfaceDescriptor* descriptor) {
36 Register registers[] = { cp, r0 }; 41 Register registers[] = { cp, r3 };
37 descriptor->Initialize(ARRAY_SIZE(registers), registers); 42 descriptor->Initialize(ARRAY_SIZE(registers), registers);
38 } 43 }
39 44
40 45
41 void NumberToStringStub::InitializeInterfaceDescriptor( 46 void NumberToStringStub::InitializeInterfaceDescriptor(
42 CodeStubInterfaceDescriptor* descriptor) { 47 CodeStubInterfaceDescriptor* descriptor) {
43 Register registers[] = { cp, r0 }; 48 Register registers[] = { cp, r3 };
44 descriptor->Initialize( 49 descriptor->Initialize(
45 ARRAY_SIZE(registers), registers, 50 ARRAY_SIZE(registers), registers,
46 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); 51 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry);
47 } 52 }
48 53
49 54
50 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( 55 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
51 CodeStubInterfaceDescriptor* descriptor) { 56 CodeStubInterfaceDescriptor* descriptor) {
52 Register registers[] = { cp, r3, r2, r1 }; 57 Register registers[] = { cp, r6, r5, r4 };
53 Representation representations[] = { 58 Representation representations[] = {
54 Representation::Tagged(), 59 Representation::Tagged(),
55 Representation::Tagged(), 60 Representation::Tagged(),
56 Representation::Smi(), 61 Representation::Smi(),
57 Representation::Tagged() }; 62 Representation::Tagged() };
58 descriptor->Initialize( 63 descriptor->Initialize(
59 ARRAY_SIZE(registers), registers, 64 ARRAY_SIZE(registers), registers,
60 Runtime::FunctionForId( 65 Runtime::FunctionForId(
61 Runtime::kCreateArrayLiteralStubBailout)->entry, 66 Runtime::kCreateArrayLiteralStubBailout)->entry,
62 representations); 67 representations);
63 } 68 }
64 69
65 70
66 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( 71 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor(
67 CodeStubInterfaceDescriptor* descriptor) { 72 CodeStubInterfaceDescriptor* descriptor) {
68 Register registers[] = { cp, r3, r2, r1, r0 }; 73 Register registers[] = { cp, r6, r5, r4, r3 };
69 descriptor->Initialize( 74 descriptor->Initialize(
70 ARRAY_SIZE(registers), registers, 75 ARRAY_SIZE(registers), registers,
71 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); 76 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
72 } 77 }
73 78
74 79
75 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( 80 void CreateAllocationSiteStub::InitializeInterfaceDescriptor(
76 CodeStubInterfaceDescriptor* descriptor) { 81 CodeStubInterfaceDescriptor* descriptor) {
77 Register registers[] = { cp, r2, r3 }; 82 Register registers[] = { cp, r5, r6 };
78 descriptor->Initialize(ARRAY_SIZE(registers), registers); 83 descriptor->Initialize(ARRAY_SIZE(registers), registers);
79 } 84 }
80 85
81 86
82 void RegExpConstructResultStub::InitializeInterfaceDescriptor( 87 void RegExpConstructResultStub::InitializeInterfaceDescriptor(
83 CodeStubInterfaceDescriptor* descriptor) { 88 CodeStubInterfaceDescriptor* descriptor) {
84 Register registers[] = { cp, r2, r1, r0 }; 89 Register registers[] = { cp, r5, r4, r3 };
85 descriptor->Initialize( 90 descriptor->Initialize(
86 ARRAY_SIZE(registers), registers, 91 ARRAY_SIZE(registers), registers,
87 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); 92 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry);
88 } 93 }
89 94
90 95
91 void TransitionElementsKindStub::InitializeInterfaceDescriptor( 96 void TransitionElementsKindStub::InitializeInterfaceDescriptor(
92 CodeStubInterfaceDescriptor* descriptor) { 97 CodeStubInterfaceDescriptor* descriptor) {
93 Register registers[] = { cp, r0, r1 }; 98 Register registers[] = { cp, r3, r4 };
94 Address entry = 99 Address entry =
95 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; 100 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry;
96 descriptor->Initialize(ARRAY_SIZE(registers), registers, 101 descriptor->Initialize(ARRAY_SIZE(registers), registers,
97 FUNCTION_ADDR(entry)); 102 FUNCTION_ADDR(entry));
98 } 103 }
99 104
100 105
101 void CompareNilICStub::InitializeInterfaceDescriptor( 106 void CompareNilICStub::InitializeInterfaceDescriptor(
102 CodeStubInterfaceDescriptor* descriptor) { 107 CodeStubInterfaceDescriptor* descriptor) {
103 Register registers[] = { cp, r0 }; 108 Register registers[] = { cp, r3 };
104 descriptor->Initialize(ARRAY_SIZE(registers), registers, 109 descriptor->Initialize(ARRAY_SIZE(registers), registers,
105 FUNCTION_ADDR(CompareNilIC_Miss)); 110 FUNCTION_ADDR(CompareNilIC_Miss));
106 descriptor->SetMissHandler( 111 descriptor->SetMissHandler(
107 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); 112 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate()));
108 } 113 }
109 114
110 115
111 const Register InterfaceDescriptor::ContextRegister() { return cp; } 116 const Register InterfaceDescriptor::ContextRegister() { return cp; }
112 117
113 118
114 static void InitializeArrayConstructorDescriptor( 119 static void InitializeArrayConstructorDescriptor(
115 CodeStubInterfaceDescriptor* descriptor, 120 CodeStubInterfaceDescriptor* descriptor,
116 int constant_stack_parameter_count) { 121 int constant_stack_parameter_count) {
117 // register state 122 // register state
118 // cp -- context 123 // cp -- context
119 // r0 -- number of arguments 124 // r3 -- number of arguments
120 // r1 -- function 125 // r4 -- function
121 // r2 -- allocation site with elements kind 126 // r5 -- allocation site with elements kind
122 Address deopt_handler = Runtime::FunctionForId( 127 Address deopt_handler = Runtime::FunctionForId(
123 Runtime::kArrayConstructor)->entry; 128 Runtime::kArrayConstructor)->entry;
124 129
125 if (constant_stack_parameter_count == 0) { 130 if (constant_stack_parameter_count == 0) {
126 Register registers[] = { cp, r1, r2 }; 131 Register registers[] = { cp, r4, r5 };
127 descriptor->Initialize(ARRAY_SIZE(registers), registers, 132 descriptor->Initialize(ARRAY_SIZE(registers), registers,
128 deopt_handler, 133 deopt_handler,
129 NULL, 134 NULL,
130 constant_stack_parameter_count, 135 constant_stack_parameter_count,
131 JS_FUNCTION_STUB_MODE); 136 JS_FUNCTION_STUB_MODE);
132 } else { 137 } else {
133 // stack param count needs (constructor pointer, and single argument) 138 // stack param count needs (constructor pointer, and single argument)
134 Register registers[] = { cp, r1, r2, r0 }; 139 Register registers[] = { cp, r4, r5, r3 };
135 Representation representations[] = { 140 Representation representations[] = {
136 Representation::Tagged(), 141 Representation::Tagged(),
137 Representation::Tagged(), 142 Representation::Tagged(),
138 Representation::Tagged(), 143 Representation::Tagged(),
139 Representation::Integer32() }; 144 Representation::Integer32() };
140 descriptor->Initialize(ARRAY_SIZE(registers), registers, 145 descriptor->Initialize(ARRAY_SIZE(registers), registers,
141 r0, 146 r3,
142 deopt_handler, 147 deopt_handler,
143 representations, 148 representations,
144 constant_stack_parameter_count, 149 constant_stack_parameter_count,
145 JS_FUNCTION_STUB_MODE, 150 JS_FUNCTION_STUB_MODE,
146 PASS_ARGUMENTS); 151 PASS_ARGUMENTS);
147 } 152 }
148 } 153 }
149 154
150 155
151 static void InitializeInternalArrayConstructorDescriptor( 156 static void InitializeInternalArrayConstructorDescriptor(
152 CodeStubInterfaceDescriptor* descriptor, 157 CodeStubInterfaceDescriptor* descriptor,
153 int constant_stack_parameter_count) { 158 int constant_stack_parameter_count) {
154 // register state 159 // register state
155 // cp -- context 160 // cp -- context
156 // r0 -- number of arguments 161 // r3 -- number of arguments
157 // r1 -- constructor function 162 // r4 -- constructor function
158 Address deopt_handler = Runtime::FunctionForId( 163 Address deopt_handler = Runtime::FunctionForId(
159 Runtime::kInternalArrayConstructor)->entry; 164 Runtime::kInternalArrayConstructor)->entry;
160 165
161 if (constant_stack_parameter_count == 0) { 166 if (constant_stack_parameter_count == 0) {
162 Register registers[] = { cp, r1 }; 167 Register registers[] = { cp, r4 };
163 descriptor->Initialize(ARRAY_SIZE(registers), registers, 168 descriptor->Initialize(ARRAY_SIZE(registers), registers,
164 deopt_handler, 169 deopt_handler,
165 NULL, 170 NULL,
166 constant_stack_parameter_count, 171 constant_stack_parameter_count,
167 JS_FUNCTION_STUB_MODE); 172 JS_FUNCTION_STUB_MODE);
168 } else { 173 } else {
169 // stack param count needs (constructor pointer, and single argument) 174 // stack param count needs (constructor pointer, and single argument)
170 Register registers[] = { cp, r1, r0 }; 175 Register registers[] = { cp, r4, r3 };
171 Representation representations[] = { 176 Representation representations[] = {
172 Representation::Tagged(), 177 Representation::Tagged(),
173 Representation::Tagged(), 178 Representation::Tagged(),
174 Representation::Integer32() }; 179 Representation::Integer32() };
175 descriptor->Initialize(ARRAY_SIZE(registers), registers, 180 descriptor->Initialize(ARRAY_SIZE(registers), registers,
176 r0, 181 r3,
177 deopt_handler, 182 deopt_handler,
178 representations, 183 representations,
179 constant_stack_parameter_count, 184 constant_stack_parameter_count,
180 JS_FUNCTION_STUB_MODE, 185 JS_FUNCTION_STUB_MODE,
181 PASS_ARGUMENTS); 186 PASS_ARGUMENTS);
182 } 187 }
183 } 188 }
184 189
185 190
186 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( 191 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
187 CodeStubInterfaceDescriptor* descriptor) { 192 CodeStubInterfaceDescriptor* descriptor) {
188 InitializeArrayConstructorDescriptor(descriptor, 0); 193 InitializeArrayConstructorDescriptor(descriptor, 0);
189 } 194 }
190 195
191 196
192 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( 197 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
193 CodeStubInterfaceDescriptor* descriptor) { 198 CodeStubInterfaceDescriptor* descriptor) {
194 InitializeArrayConstructorDescriptor(descriptor, 1); 199 InitializeArrayConstructorDescriptor(descriptor, 1);
195 } 200 }
196 201
197 202
198 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( 203 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
199 CodeStubInterfaceDescriptor* descriptor) { 204 CodeStubInterfaceDescriptor* descriptor) {
200 InitializeArrayConstructorDescriptor(descriptor, -1); 205 InitializeArrayConstructorDescriptor(descriptor, -1);
201 } 206 }
202 207
203 208
204 void ToBooleanStub::InitializeInterfaceDescriptor( 209 void ToBooleanStub::InitializeInterfaceDescriptor(
205 CodeStubInterfaceDescriptor* descriptor) { 210 CodeStubInterfaceDescriptor* descriptor) {
206 Register registers[] = { cp, r0 }; 211 Register registers[] = { cp, r3 };
207 descriptor->Initialize(ARRAY_SIZE(registers), registers, 212 descriptor->Initialize(ARRAY_SIZE(registers), registers,
208 FUNCTION_ADDR(ToBooleanIC_Miss)); 213 FUNCTION_ADDR(ToBooleanIC_Miss));
209 descriptor->SetMissHandler( 214 descriptor->SetMissHandler(
210 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); 215 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate()));
211 } 216 }
212 217
213 218
214 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( 219 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
215 CodeStubInterfaceDescriptor* descriptor) { 220 CodeStubInterfaceDescriptor* descriptor) {
216 InitializeInternalArrayConstructorDescriptor(descriptor, 0); 221 InitializeInternalArrayConstructorDescriptor(descriptor, 0);
217 } 222 }
218 223
219 224
220 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( 225 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
221 CodeStubInterfaceDescriptor* descriptor) { 226 CodeStubInterfaceDescriptor* descriptor) {
222 InitializeInternalArrayConstructorDescriptor(descriptor, 1); 227 InitializeInternalArrayConstructorDescriptor(descriptor, 1);
223 } 228 }
224 229
225 230
226 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( 231 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
227 CodeStubInterfaceDescriptor* descriptor) { 232 CodeStubInterfaceDescriptor* descriptor) {
228 InitializeInternalArrayConstructorDescriptor(descriptor, -1); 233 InitializeInternalArrayConstructorDescriptor(descriptor, -1);
229 } 234 }
230 235
231 236
232 void BinaryOpICStub::InitializeInterfaceDescriptor( 237 void BinaryOpICStub::InitializeInterfaceDescriptor(
233 CodeStubInterfaceDescriptor* descriptor) { 238 CodeStubInterfaceDescriptor* descriptor) {
234 Register registers[] = { cp, r1, r0 }; 239 Register registers[] = { cp, r4, r3 };
235 descriptor->Initialize(ARRAY_SIZE(registers), registers, 240 descriptor->Initialize(ARRAY_SIZE(registers), registers,
236 FUNCTION_ADDR(BinaryOpIC_Miss)); 241 FUNCTION_ADDR(BinaryOpIC_Miss));
237 descriptor->SetMissHandler( 242 descriptor->SetMissHandler(
238 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); 243 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate()));
239 } 244 }
240 245
241 246
242 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( 247 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor(
243 CodeStubInterfaceDescriptor* descriptor) { 248 CodeStubInterfaceDescriptor* descriptor) {
244 Register registers[] = { cp, r2, r1, r0 }; 249 Register registers[] = { cp, r5, r4, r3 };
245 descriptor->Initialize(ARRAY_SIZE(registers), registers, 250 descriptor->Initialize(ARRAY_SIZE(registers), registers,
246 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); 251 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite));
247 } 252 }
248 253
249 254
250 void StringAddStub::InitializeInterfaceDescriptor( 255 void StringAddStub::InitializeInterfaceDescriptor(
251 CodeStubInterfaceDescriptor* descriptor) { 256 CodeStubInterfaceDescriptor* descriptor) {
252 Register registers[] = { cp, r1, r0 }; 257 Register registers[] = { cp, r4, r3 };
253 descriptor->Initialize( 258 descriptor->Initialize(
254 ARRAY_SIZE(registers), registers, 259 ARRAY_SIZE(registers), registers,
255 Runtime::FunctionForId(Runtime::kStringAdd)->entry); 260 Runtime::FunctionForId(Runtime::kStringAdd)->entry);
256 } 261 }
257 262
258 263
259 void CallDescriptors::InitializeForIsolate(Isolate* isolate) { 264 void CallDescriptors::InitializeForIsolate(Isolate* isolate) {
260 static PlatformInterfaceDescriptor default_descriptor =
261 PlatformInterfaceDescriptor(CAN_INLINE_TARGET_ADDRESS);
262
263 static PlatformInterfaceDescriptor noInlineDescriptor =
264 PlatformInterfaceDescriptor(NEVER_INLINE_TARGET_ADDRESS);
265
266 { 265 {
267 CallInterfaceDescriptor* descriptor = 266 CallInterfaceDescriptor* descriptor =
268 isolate->call_descriptor(Isolate::ArgumentAdaptorCall); 267 isolate->call_descriptor(Isolate::ArgumentAdaptorCall);
269 Register registers[] = { cp, // context 268 Register registers[] = { cp, // context
270 r1, // JSFunction 269 r4, // JSFunction
271 r0, // actual number of arguments 270 r3, // actual number of arguments
272 r2, // expected number of arguments 271 r5, // expected number of arguments
273 }; 272 };
274 Representation representations[] = { 273 Representation representations[] = {
275 Representation::Tagged(), // context 274 Representation::Tagged(), // context
276 Representation::Tagged(), // JSFunction 275 Representation::Tagged(), // JSFunction
277 Representation::Integer32(), // actual number of arguments 276 Representation::Integer32(), // actual number of arguments
278 Representation::Integer32(), // expected number of arguments 277 Representation::Integer32(), // expected number of arguments
279 }; 278 };
280 descriptor->Initialize(ARRAY_SIZE(registers), registers, 279 descriptor->Initialize(ARRAY_SIZE(registers), registers, representations);
281 representations, &default_descriptor);
282 } 280 }
283 { 281 {
284 CallInterfaceDescriptor* descriptor = 282 CallInterfaceDescriptor* descriptor =
285 isolate->call_descriptor(Isolate::KeyedCall); 283 isolate->call_descriptor(Isolate::KeyedCall);
286 Register registers[] = { cp, // context 284 Register registers[] = { cp, // context
287 r2, // key 285 r5, // key
288 }; 286 };
289 Representation representations[] = { 287 Representation representations[] = {
290 Representation::Tagged(), // context 288 Representation::Tagged(), // context
291 Representation::Tagged(), // key 289 Representation::Tagged(), // key
292 }; 290 };
293 descriptor->Initialize(ARRAY_SIZE(registers), registers, 291 descriptor->Initialize(ARRAY_SIZE(registers), registers, representations);
294 representations, &noInlineDescriptor);
295 } 292 }
296 { 293 {
297 CallInterfaceDescriptor* descriptor = 294 CallInterfaceDescriptor* descriptor =
298 isolate->call_descriptor(Isolate::NamedCall); 295 isolate->call_descriptor(Isolate::NamedCall);
299 Register registers[] = { cp, // context 296 Register registers[] = { cp, // context
300 r2, // name 297 r5, // name
301 }; 298 };
302 Representation representations[] = { 299 Representation representations[] = {
303 Representation::Tagged(), // context 300 Representation::Tagged(), // context
304 Representation::Tagged(), // name 301 Representation::Tagged(), // name
305 }; 302 };
306 descriptor->Initialize(ARRAY_SIZE(registers), registers, 303 descriptor->Initialize(ARRAY_SIZE(registers), registers, representations);
307 representations, &noInlineDescriptor);
308 } 304 }
309 { 305 {
310 CallInterfaceDescriptor* descriptor = 306 CallInterfaceDescriptor* descriptor =
311 isolate->call_descriptor(Isolate::CallHandler); 307 isolate->call_descriptor(Isolate::CallHandler);
312 Register registers[] = { cp, // context 308 Register registers[] = { cp, // context
313 r0, // receiver 309 r3, // receiver
314 }; 310 };
315 Representation representations[] = { 311 Representation representations[] = {
316 Representation::Tagged(), // context 312 Representation::Tagged(), // context
317 Representation::Tagged(), // receiver 313 Representation::Tagged(), // receiver
318 }; 314 };
319 descriptor->Initialize(ARRAY_SIZE(registers), registers, 315 descriptor->Initialize(ARRAY_SIZE(registers), registers, representations);
320 representations, &default_descriptor);
321 } 316 }
322 { 317 {
323 CallInterfaceDescriptor* descriptor = 318 CallInterfaceDescriptor* descriptor =
324 isolate->call_descriptor(Isolate::ApiFunctionCall); 319 isolate->call_descriptor(Isolate::ApiFunctionCall);
325 Register registers[] = { cp, // context 320 Register registers[] = { cp, // context
326 r0, // callee 321 r3, // callee
327 r4, // call_data 322 r7, // call_data
328 r2, // holder 323 r5, // holder
329 r1, // api_function_address 324 r4, // api_function_address
330 }; 325 };
331 Representation representations[] = { 326 Representation representations[] = {
332 Representation::Tagged(), // context 327 Representation::Tagged(), // context
333 Representation::Tagged(), // callee 328 Representation::Tagged(), // callee
334 Representation::Tagged(), // call_data 329 Representation::Tagged(), // call_data
335 Representation::Tagged(), // holder 330 Representation::Tagged(), // holder
336 Representation::External(), // api_function_address 331 Representation::External(), // api_function_address
337 }; 332 };
338 descriptor->Initialize(ARRAY_SIZE(registers), registers, 333 descriptor->Initialize(ARRAY_SIZE(registers), registers, representations);
339 representations, &default_descriptor);
340 } 334 }
341 } 335 }
342 336
343 337
344 #define __ ACCESS_MASM(masm) 338 #define __ ACCESS_MASM(masm)
345 339
346 340
347 static void EmitIdenticalObjectComparison(MacroAssembler* masm, 341 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
348 Label* slow, 342 Label* slow,
349 Condition cond); 343 Condition cond);
(...skipping 11 matching lines...) Expand all
361 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { 355 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
362 // Update the static counter each time a new code stub is generated. 356 // Update the static counter each time a new code stub is generated.
363 isolate()->counters()->code_stubs()->Increment(); 357 isolate()->counters()->code_stubs()->Increment();
364 358
365 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(); 359 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor();
366 int param_count = descriptor->GetEnvironmentParameterCount(); 360 int param_count = descriptor->GetEnvironmentParameterCount();
367 { 361 {
368 // Call the runtime system in a fresh internal frame. 362 // Call the runtime system in a fresh internal frame.
369 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 363 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
370 ASSERT(param_count == 0 || 364 ASSERT(param_count == 0 ||
371 r0.is(descriptor->GetEnvironmentParameterRegister( 365 r3.is(descriptor->GetEnvironmentParameterRegister(
372 param_count - 1))); 366 param_count - 1)));
373 // Push arguments 367 // Push arguments
374 for (int i = 0; i < param_count; ++i) { 368 for (int i = 0; i < param_count; ++i) {
375 __ push(descriptor->GetEnvironmentParameterRegister(i)); 369 __ push(descriptor->GetEnvironmentParameterRegister(i));
376 } 370 }
377 ExternalReference miss = descriptor->miss_handler(); 371 ExternalReference miss = descriptor->miss_handler();
378 __ CallExternalReference(miss, param_count); 372 __ CallExternalReference(miss, param_count);
379 } 373 }
380 374
381 __ Ret(); 375 __ Ret();
382 } 376 }
383 377
384 378
379 #if 0 // roohack unused?
385 // Takes a Smi and converts to an IEEE 64 bit floating point value in two 380 // Takes a Smi and converts to an IEEE 64 bit floating point value in two
386 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and 381 // registers. The format is 1 sign bit, 11 exponent bits (biased 1023) and
387 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a 382 // 52 fraction bits (20 in the first word, 32 in the second). Zeros is a
388 // scratch register. Destroys the source register. No GC occurs during this 383 // scratch register. Destroys the source register. No GC occurs during this
389 // stub so you don't have to set up the frame. 384 // stub so you don't have to set up the frame.
390 class ConvertToDoubleStub : public PlatformCodeStub { 385 class ConvertToDoubleStub : public PlatformCodeStub {
391 public: 386 public:
392 ConvertToDoubleStub(Isolate* isolate, 387 ConvertToDoubleStub(Isolate* isolate,
393 Register result_reg_1, 388 Register result_reg_1,
394 Register result_reg_2, 389 Register result_reg_2,
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. 463 // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0.
469 __ mov(source_, Operand(source_, LSL, zeros_)); 464 __ mov(source_, Operand(source_, LSL, zeros_));
470 // Compute lower part of fraction (last 12 bits). 465 // Compute lower part of fraction (last 12 bits).
471 __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord)); 466 __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord));
472 // And the top (top 20 bits). 467 // And the top (top 20 bits).
473 __ orr(exponent, 468 __ orr(exponent,
474 exponent, 469 exponent,
475 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); 470 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord));
476 __ Ret(); 471 __ Ret();
477 } 472 }
473 #endif // roohack
478 474
479 475
480 void DoubleToIStub::Generate(MacroAssembler* masm) { 476 void DoubleToIStub::Generate(MacroAssembler* masm) {
481 Label out_of_range, only_low, negate, done; 477 Label out_of_range, only_low, negate, done, fastpath_done;
482 Register input_reg = source(); 478 Register input_reg = source();
483 Register result_reg = destination(); 479 Register result_reg = destination();
484 ASSERT(is_truncating()); 480 ASSERT(is_truncating());
485 481
486 int double_offset = offset(); 482 int double_offset = offset();
487 // Account for saved regs if input is sp.
488 if (input_reg.is(sp)) double_offset += 3 * kPointerSize;
489 483
484 // Immediate values for this stub fit in instructions, so it's safe to use ip.
490 Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg); 485 Register scratch = GetRegisterThatIsNotOneOf(input_reg, result_reg);
491 Register scratch_low = 486 Register scratch_low =
492 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch); 487 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
493 Register scratch_high = 488 Register scratch_high =
494 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low); 489 GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low);
495 LowDwVfpRegister double_scratch = kScratchDoubleReg; 490 DoubleRegister double_scratch = kScratchDoubleReg;
496 491
497 __ Push(scratch_high, scratch_low, scratch); 492 __ push(scratch);
493 // Account for saved regs if input is sp.
494 if (input_reg.is(sp)) double_offset += kPointerSize;
498 495
499 if (!skip_fastpath()) { 496 if (!skip_fastpath()) {
500 // Load double input. 497 // Load double input.
501 __ vldr(double_scratch, MemOperand(input_reg, double_offset)); 498 __ lfd(double_scratch, MemOperand(input_reg, double_offset));
502 __ vmov(scratch_low, scratch_high, double_scratch);
503 499
504 // Do fast-path convert from double to int. 500 // Do fast-path convert from double to int.
505 __ vcvt_s32_f64(double_scratch.low(), double_scratch); 501 __ ConvertDoubleToInt64(double_scratch, result_reg,
506 __ vmov(result_reg, double_scratch.low()); 502 #if !V8_TARGET_ARCH_PPC64
503 scratch,
504 #endif
505 d0);
507 506
508 // If result is not saturated (0x7fffffff or 0x80000000), we are done. 507 // Test for overflow
509 __ sub(scratch, result_reg, Operand(1)); 508 #if V8_TARGET_ARCH_PPC64
510 __ cmp(scratch, Operand(0x7ffffffe)); 509 __ TestIfInt32(result_reg, scratch, r0);
511 __ b(lt, &done); 510 #else
512 } else { 511 __ TestIfInt32(scratch, result_reg, r0);
513 // We've already done MacroAssembler::TryFastTruncatedDoubleToILoad, so we 512 #endif
514 // know exponent > 31, so we can skip the vcvt_s32_f64 which will saturate. 513 __ beq(&fastpath_done);
515 if (double_offset == 0) {
516 __ ldm(ia, input_reg, scratch_low.bit() | scratch_high.bit());
517 } else {
518 __ ldr(scratch_low, MemOperand(input_reg, double_offset));
519 __ ldr(scratch_high, MemOperand(input_reg, double_offset + kIntSize));
520 }
521 } 514 }
522 515
523 __ Ubfx(scratch, scratch_high, 516 __ Push(scratch_high, scratch_low);
524 HeapNumber::kExponentShift, HeapNumber::kExponentBits); 517 // Account for saved regs if input is sp.
518 if (input_reg.is(sp)) double_offset += 2 * kPointerSize;
519
520 __ lwz(scratch_high, MemOperand(input_reg, double_offset +
521 Register::kExponentOffset));
522 __ lwz(scratch_low, MemOperand(input_reg, double_offset +
523 Register::kMantissaOffset));
524
525 __ ExtractBitMask(scratch, scratch_high, HeapNumber::kExponentMask);
525 // Load scratch with exponent - 1. This is faster than loading 526 // Load scratch with exponent - 1. This is faster than loading
526 // with exponent because Bias + 1 = 1024 which is an *ARM* immediate value. 527 // with exponent because Bias + 1 = 1024 which is a *PPC* immediate value.
527 STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024); 528 STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024);
528 __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias + 1)); 529 __ subi(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
529 // If exponent is greater than or equal to 84, the 32 less significant 530 // If exponent is greater than or equal to 84, the 32 less significant
530 // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits), 531 // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
531 // the result is 0. 532 // the result is 0.
532 // Compare exponent with 84 (compare exponent - 1 with 83). 533 // Compare exponent with 84 (compare exponent - 1 with 83).
533 __ cmp(scratch, Operand(83)); 534 __ cmpi(scratch, Operand(83));
534 __ b(ge, &out_of_range); 535 __ bge(&out_of_range);
535 536
536 // If we reach this code, 31 <= exponent <= 83. 537 // If we reach this code, 31 <= exponent <= 83.
537 // So, we don't have to handle cases where 0 <= exponent <= 20 for 538 // So, we don't have to handle cases where 0 <= exponent <= 20 for
538 // which we would need to shift right the high part of the mantissa. 539 // which we would need to shift right the high part of the mantissa.
539 // Scratch contains exponent - 1. 540 // Scratch contains exponent - 1.
540 // Load scratch with 52 - exponent (load with 51 - (exponent - 1)). 541 // Load scratch with 52 - exponent (load with 51 - (exponent - 1)).
541 __ rsb(scratch, scratch, Operand(51), SetCC); 542 __ subfic(scratch, scratch, Operand(51));
542 __ b(ls, &only_low); 543 __ cmpi(scratch, Operand::Zero());
544 __ ble(&only_low);
543 // 21 <= exponent <= 51, shift scratch_low and scratch_high 545 // 21 <= exponent <= 51, shift scratch_low and scratch_high
544 // to generate the result. 546 // to generate the result.
545 __ mov(scratch_low, Operand(scratch_low, LSR, scratch)); 547 __ srw(scratch_low, scratch_low, scratch);
546 // Scratch contains: 52 - exponent. 548 // Scratch contains: 52 - exponent.
547 // We needs: exponent - 20. 549 // We needs: exponent - 20.
548 // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20. 550 // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20.
549 __ rsb(scratch, scratch, Operand(32)); 551 __ subfic(scratch, scratch, Operand(32));
550 __ Ubfx(result_reg, scratch_high, 552 __ ExtractBitMask(result_reg, scratch_high, HeapNumber::kMantissaMask);
551 0, HeapNumber::kMantissaBitsInTopWord);
552 // Set the implicit 1 before the mantissa part in scratch_high. 553 // Set the implicit 1 before the mantissa part in scratch_high.
553 __ orr(result_reg, result_reg, 554 STATIC_ASSERT(HeapNumber::kMantissaBitsInTopWord >= 16);
554 Operand(1 << HeapNumber::kMantissaBitsInTopWord)); 555 __ oris(result_reg, result_reg,
555 __ orr(result_reg, scratch_low, Operand(result_reg, LSL, scratch)); 556 Operand(1 << ((HeapNumber::kMantissaBitsInTopWord) - 16)));
557 __ slw(r0, result_reg, scratch);
558 __ orx(result_reg, scratch_low, r0);
556 __ b(&negate); 559 __ b(&negate);
557 560
558 __ bind(&out_of_range); 561 __ bind(&out_of_range);
559 __ mov(result_reg, Operand::Zero()); 562 __ mov(result_reg, Operand::Zero());
560 __ b(&done); 563 __ b(&done);
561 564
562 __ bind(&only_low); 565 __ bind(&only_low);
563 // 52 <= exponent <= 83, shift only scratch_low. 566 // 52 <= exponent <= 83, shift only scratch_low.
564 // On entry, scratch contains: 52 - exponent. 567 // On entry, scratch contains: 52 - exponent.
565 __ rsb(scratch, scratch, Operand::Zero()); 568 __ neg(scratch, scratch);
566 __ mov(result_reg, Operand(scratch_low, LSL, scratch)); 569 __ slw(result_reg, scratch_low, scratch);
567 570
568 __ bind(&negate); 571 __ bind(&negate);
569 // If input was positive, scratch_high ASR 31 equals 0 and 572 // If input was positive, scratch_high ASR 31 equals 0 and
570 // scratch_high LSR 31 equals zero. 573 // scratch_high LSR 31 equals zero.
571 // New result = (result eor 0) + 0 = result. 574 // New result = (result eor 0) + 0 = result.
572 // If the input was negative, we have to negate the result. 575 // If the input was negative, we have to negate the result.
573 // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1. 576 // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1.
574 // New result = (result eor 0xffffffff) + 1 = 0 - result. 577 // New result = (result eor 0xffffffff) + 1 = 0 - result.
575 __ eor(result_reg, result_reg, Operand(scratch_high, ASR, 31)); 578 __ srawi(r0, scratch_high, 31);
576 __ add(result_reg, result_reg, Operand(scratch_high, LSR, 31)); 579 #if V8_TARGET_ARCH_PPC64
580 __ srdi(r0, r0, Operand(32));
581 #endif
582 __ xor_(result_reg, result_reg, r0);
583 __ srwi(r0, scratch_high, Operand(31));
584 __ add(result_reg, result_reg, r0);
577 585
578 __ bind(&done); 586 __ bind(&done);
587 __ Pop(scratch_high, scratch_low);
579 588
580 __ Pop(scratch_high, scratch_low, scratch); 589 __ bind(&fastpath_done);
590 __ pop(scratch);
591
581 __ Ret(); 592 __ Ret();
582 } 593 }
583 594
584 595
596 #if 0 // roohack unused?
585 void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( 597 void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(
586 Isolate* isolate) { 598 Isolate* isolate) {
587 WriteInt32ToHeapNumberStub stub1(isolate, r1, r0, r2); 599 WriteInt32ToHeapNumberStub stub1(isolate, r4, r3, r5);
588 WriteInt32ToHeapNumberStub stub2(isolate, r2, r0, r3); 600 WriteInt32ToHeapNumberStub stub2(isolate, r5, r3, r6);
589 stub1.GetCode(); 601 stub1.GetCode();
590 stub2.GetCode(); 602 stub2.GetCode();
591 } 603 }
592 604
593 605
594 // See comment for class. 606 // See comment for class.
595 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { 607 void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
596 Label max_negative_int; 608 Label max_negative_int;
597 // the_int_ has the answer which is a signed int32 but not a Smi. 609 // the_int_ has the answer which is a signed int32 but not a Smi.
598 // We test for the special value that has a different exponent. This test 610 // We test for the special value that has a different exponent. This test
(...skipping 29 matching lines...) Expand all
628 // a double because it uses a sign bit instead of using two's complement. 640 // a double because it uses a sign bit instead of using two's complement.
629 // The actual mantissa bits stored are all 0 because the implicit most 641 // The actual mantissa bits stored are all 0 because the implicit most
630 // significant 1 bit is not stored. 642 // significant 1 bit is not stored.
631 non_smi_exponent += 1 << HeapNumber::kExponentShift; 643 non_smi_exponent += 1 << HeapNumber::kExponentShift;
632 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); 644 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent));
633 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); 645 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset));
634 __ mov(ip, Operand::Zero()); 646 __ mov(ip, Operand::Zero());
635 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); 647 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset));
636 __ Ret(); 648 __ Ret();
637 } 649 }
638 650 #endif // roohack
639 651
640 // Handle the case where the lhs and rhs are the same object. 652 // Handle the case where the lhs and rhs are the same object.
641 // Equality is almost reflexive (everything but NaN), so this is a test 653 // Equality is almost reflexive (everything but NaN), so this is a test
642 // for "identity and not NaN". 654 // for "identity and not NaN".
643 static void EmitIdenticalObjectComparison(MacroAssembler* masm, 655 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
644 Label* slow, 656 Label* slow,
645 Condition cond) { 657 Condition cond) {
646 Label not_identical; 658 Label not_identical;
647 Label heap_number, return_equal; 659 Label heap_number, return_equal;
648 __ cmp(r0, r1); 660 __ cmp(r3, r4);
649 __ b(ne, &not_identical); 661 __ bne(&not_identical);
650 662
651 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 663 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
652 // so we do the second best thing - test it ourselves. 664 // so we do the second best thing - test it ourselves.
653 // They are both equal and they are not both Smis so both of them are not 665 // They are both equal and they are not both Smis so both of them are not
654 // Smis. If it's not a heap number, then return equal. 666 // Smis. If it's not a heap number, then return equal.
655 if (cond == lt || cond == gt) { 667 if (cond == lt || cond == gt) {
656 __ CompareObjectType(r0, r4, r4, FIRST_SPEC_OBJECT_TYPE); 668 __ CompareObjectType(r3, r7, r7, FIRST_SPEC_OBJECT_TYPE);
657 __ b(ge, slow); 669 __ bge(slow);
658 } else { 670 } else {
659 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); 671 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE);
660 __ b(eq, &heap_number); 672 __ beq(&heap_number);
661 // Comparing JS objects with <=, >= is complicated. 673 // Comparing JS objects with <=, >= is complicated.
662 if (cond != eq) { 674 if (cond != eq) {
663 __ cmp(r4, Operand(FIRST_SPEC_OBJECT_TYPE)); 675 __ cmpi(r7, Operand(FIRST_SPEC_OBJECT_TYPE));
664 __ b(ge, slow); 676 __ bge(slow);
665 // Normally here we fall through to return_equal, but undefined is 677 // Normally here we fall through to return_equal, but undefined is
666 // special: (undefined == undefined) == true, but 678 // special: (undefined == undefined) == true, but
667 // (undefined <= undefined) == false! See ECMAScript 11.8.5. 679 // (undefined <= undefined) == false! See ECMAScript 11.8.5.
668 if (cond == le || cond == ge) { 680 if (cond == le || cond == ge) {
669 __ cmp(r4, Operand(ODDBALL_TYPE)); 681 __ cmpi(r7, Operand(ODDBALL_TYPE));
670 __ b(ne, &return_equal); 682 __ bne(&return_equal);
671 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 683 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
672 __ cmp(r0, r2); 684 __ cmp(r3, r5);
673 __ b(ne, &return_equal); 685 __ bne(&return_equal);
674 if (cond == le) { 686 if (cond == le) {
675 // undefined <= undefined should fail. 687 // undefined <= undefined should fail.
676 __ mov(r0, Operand(GREATER)); 688 __ li(r3, Operand(GREATER));
677 } else { 689 } else {
678 // undefined >= undefined should fail. 690 // undefined >= undefined should fail.
679 __ mov(r0, Operand(LESS)); 691 __ li(r3, Operand(LESS));
680 } 692 }
681 __ Ret(); 693 __ Ret();
682 } 694 }
683 } 695 }
684 } 696 }
685 697
686 __ bind(&return_equal); 698 __ bind(&return_equal);
687 if (cond == lt) { 699 if (cond == lt) {
688 __ mov(r0, Operand(GREATER)); // Things aren't less than themselves. 700 __ li(r3, Operand(GREATER)); // Things aren't less than themselves.
689 } else if (cond == gt) { 701 } else if (cond == gt) {
690 __ mov(r0, Operand(LESS)); // Things aren't greater than themselves. 702 __ li(r3, Operand(LESS)); // Things aren't greater than themselves.
691 } else { 703 } else {
692 __ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, === themselves. 704 __ li(r3, Operand(EQUAL)); // Things are <=, >=, ==, === themselves.
693 } 705 }
694 __ Ret(); 706 __ Ret();
695 707
696 // For less and greater we don't have to check for NaN since the result of 708 // For less and greater we don't have to check for NaN since the result of
697 // x < x is false regardless. For the others here is some code to check 709 // x < x is false regardless. For the others here is some code to check
698 // for NaN. 710 // for NaN.
699 if (cond != lt && cond != gt) { 711 if (cond != lt && cond != gt) {
700 __ bind(&heap_number); 712 __ bind(&heap_number);
701 // It is a heap number, so return non-equal if it's NaN and equal if it's 713 // It is a heap number, so return non-equal if it's NaN and equal if it's
702 // not NaN. 714 // not NaN.
703 715
704 // The representation of NaN values has all exponent bits (52..62) set, 716 // The representation of NaN values has all exponent bits (52..62) set,
705 // and not all mantissa bits (0..51) clear. 717 // and not all mantissa bits (0..51) clear.
706 // Read top bits of double representation (second word of value). 718 // Read top bits of double representation (second word of value).
707 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 719 __ lwz(r5, FieldMemOperand(r3, HeapNumber::kExponentOffset));
708 // Test that exponent bits are all set. 720 // Test that exponent bits are all set.
709 __ Sbfx(r3, r2, HeapNumber::kExponentShift, HeapNumber::kExponentBits); 721 STATIC_ASSERT(HeapNumber::kExponentMask == 0x7ff00000u);
710 // NaNs have all-one exponents so they sign extend to -1. 722 __ ExtractBitMask(r6, r5, HeapNumber::kExponentMask);
711 __ cmp(r3, Operand(-1)); 723 __ cmpli(r6, Operand(0x7ff));
712 __ b(ne, &return_equal); 724 __ bne(&return_equal);
713 725
714 // Shift out flag and all exponent bits, retaining only mantissa. 726 // Shift out flag and all exponent bits, retaining only mantissa.
715 __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord)); 727 __ slwi(r5, r5, Operand(HeapNumber::kNonMantissaBitsInTopWord));
716 // Or with all low-bits of mantissa. 728 // Or with all low-bits of mantissa.
717 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 729 __ lwz(r6, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
718 __ orr(r0, r3, Operand(r2), SetCC); 730 __ orx(r3, r6, r5);
719 // For equal we already have the right value in r0: Return zero (equal) 731 __ cmpi(r3, Operand::Zero());
732 // For equal we already have the right value in r3: Return zero (equal)
720 // if all bits in mantissa are zero (it's an Infinity) and non-zero if 733 // if all bits in mantissa are zero (it's an Infinity) and non-zero if
721 // not (it's a NaN). For <= and >= we need to load r0 with the failing 734 // not (it's a NaN). For <= and >= we need to load r0 with the failing
722 // value if it's a NaN. 735 // value if it's a NaN.
723 if (cond != eq) { 736 if (cond != eq) {
737 Label not_equal;
738 __ bne(&not_equal);
724 // All-zero means Infinity means equal. 739 // All-zero means Infinity means equal.
725 __ Ret(eq); 740 __ Ret();
741 __ bind(&not_equal);
726 if (cond == le) { 742 if (cond == le) {
727 __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail. 743 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail.
728 } else { 744 } else {
729 __ mov(r0, Operand(LESS)); // NaN >= NaN should fail. 745 __ li(r3, Operand(LESS)); // NaN >= NaN should fail.
730 } 746 }
731 } 747 }
732 __ Ret(); 748 __ Ret();
733 } 749 }
734 // No fall through here. 750 // No fall through here.
735 751
736 __ bind(&not_identical); 752 __ bind(&not_identical);
737 } 753 }
738 754
739 755
740 // See comment at call site. 756 // See comment at call site.
741 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 757 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
742 Register lhs, 758 Register lhs,
743 Register rhs, 759 Register rhs,
744 Label* lhs_not_nan, 760 Label* lhs_not_nan,
745 Label* slow, 761 Label* slow,
746 bool strict) { 762 bool strict) {
747 ASSERT((lhs.is(r0) && rhs.is(r1)) || 763 ASSERT((lhs.is(r3) && rhs.is(r4)) ||
748 (lhs.is(r1) && rhs.is(r0))); 764 (lhs.is(r4) && rhs.is(r3)));
749 765
750 Label rhs_is_smi; 766 Label rhs_is_smi;
751 __ JumpIfSmi(rhs, &rhs_is_smi); 767 __ JumpIfSmi(rhs, &rhs_is_smi);
752 768
753 // Lhs is a Smi. Check whether the rhs is a heap number. 769 // Lhs is a Smi. Check whether the rhs is a heap number.
754 __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE); 770 __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE);
755 if (strict) { 771 if (strict) {
756 // If rhs is not a number and lhs is a Smi then strict equality cannot 772 // If rhs is not a number and lhs is a Smi then strict equality cannot
757 // succeed. Return non-equal 773 // succeed. Return non-equal
758 // If rhs is r0 then there is already a non zero value in it. 774 // If rhs is r3 then there is already a non zero value in it.
759 if (!rhs.is(r0)) { 775 Label skip;
760 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); 776 __ beq(&skip);
777 if (!rhs.is(r3)) {
778 __ mov(r3, Operand(NOT_EQUAL));
761 } 779 }
762 __ Ret(ne); 780 __ Ret();
781 __ bind(&skip);
763 } else { 782 } else {
764 // Smi compared non-strictly with a non-Smi non-heap-number. Call 783 // Smi compared non-strictly with a non-Smi non-heap-number. Call
765 // the runtime. 784 // the runtime.
766 __ b(ne, slow); 785 __ bne(slow);
767 } 786 }
768 787
769 // Lhs is a smi, rhs is a number. 788 // Lhs is a smi, rhs is a number.
770 // Convert lhs to a double in d7. 789 // Convert lhs to a double in d7.
771 __ SmiToDouble(d7, lhs); 790 __ SmiToDouble(d7, lhs);
772 // Load the double from rhs, tagged HeapNumber r0, to d6. 791 // Load the double from rhs, tagged HeapNumber r3, to d6.
773 __ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag); 792 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
774 793
775 // We now have both loaded as doubles but we can skip the lhs nan check 794 // We now have both loaded as doubles but we can skip the lhs nan check
776 // since it's a smi. 795 // since it's a smi.
777 __ jmp(lhs_not_nan); 796 __ b(lhs_not_nan);
778 797
779 __ bind(&rhs_is_smi); 798 __ bind(&rhs_is_smi);
780 // Rhs is a smi. Check whether the non-smi lhs is a heap number. 799 // Rhs is a smi. Check whether the non-smi lhs is a heap number.
781 __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE); 800 __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE);
782 if (strict) { 801 if (strict) {
783 // If lhs is not a number and rhs is a smi then strict equality cannot 802 // If lhs is not a number and rhs is a smi then strict equality cannot
784 // succeed. Return non-equal. 803 // succeed. Return non-equal.
785 // If lhs is r0 then there is already a non zero value in it. 804 // If lhs is r3 then there is already a non zero value in it.
786 if (!lhs.is(r0)) { 805 Label skip;
787 __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne); 806 __ beq(&skip);
807 if (!lhs.is(r3)) {
808 __ mov(r3, Operand(NOT_EQUAL));
788 } 809 }
789 __ Ret(ne); 810 __ Ret();
811 __ bind(&skip);
790 } else { 812 } else {
791 // Smi compared non-strictly with a non-smi non-heap-number. Call 813 // Smi compared non-strictly with a non-smi non-heap-number. Call
792 // the runtime. 814 // the runtime.
793 __ b(ne, slow); 815 __ bne(slow);
794 } 816 }
795 817
796 // Rhs is a smi, lhs is a heap number. 818 // Rhs is a smi, lhs is a heap number.
797 // Load the double from lhs, tagged HeapNumber r1, to d7. 819 // Load the double from lhs, tagged HeapNumber r4, to d7.
798 __ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag); 820 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
799 // Convert rhs to a double in d6 . 821 // Convert rhs to a double in d6.
800 __ SmiToDouble(d6, rhs); 822 __ SmiToDouble(d6, rhs);
801 // Fall through to both_loaded_as_doubles. 823 // Fall through to both_loaded_as_doubles.
802 } 824 }
803 825
804 826
805 // See comment at call site. 827 // See comment at call site.
806 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, 828 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
807 Register lhs, 829 Register lhs,
808 Register rhs) { 830 Register rhs) {
809 ASSERT((lhs.is(r0) && rhs.is(r1)) || 831 ASSERT((lhs.is(r3) && rhs.is(r4)) ||
810 (lhs.is(r1) && rhs.is(r0))); 832 (lhs.is(r4) && rhs.is(r3)));
811 833
812 // If either operand is a JS object or an oddball value, then they are 834 // If either operand is a JS object or an oddball value, then they are
813 // not equal since their pointers are different. 835 // not equal since their pointers are different.
814 // There is no test for undetectability in strict equality. 836 // There is no test for undetectability in strict equality.
815 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); 837 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
816 Label first_non_object; 838 Label first_non_object;
817 // Get the type of the first operand into r2 and compare it with 839 // Get the type of the first operand into r5 and compare it with
818 // FIRST_SPEC_OBJECT_TYPE. 840 // FIRST_SPEC_OBJECT_TYPE.
819 __ CompareObjectType(rhs, r2, r2, FIRST_SPEC_OBJECT_TYPE); 841 __ CompareObjectType(rhs, r5, r5, FIRST_SPEC_OBJECT_TYPE);
820 __ b(lt, &first_non_object); 842 __ blt(&first_non_object);
821 843
822 // Return non-zero (r0 is not zero) 844 // Return non-zero (r3 is not zero)
823 Label return_not_equal; 845 Label return_not_equal;
824 __ bind(&return_not_equal); 846 __ bind(&return_not_equal);
825 __ Ret(); 847 __ Ret();
826 848
827 __ bind(&first_non_object); 849 __ bind(&first_non_object);
828 // Check for oddballs: true, false, null, undefined. 850 // Check for oddballs: true, false, null, undefined.
829 __ cmp(r2, Operand(ODDBALL_TYPE)); 851 __ cmpi(r5, Operand(ODDBALL_TYPE));
830 __ b(eq, &return_not_equal); 852 __ beq(&return_not_equal);
831 853
832 __ CompareObjectType(lhs, r3, r3, FIRST_SPEC_OBJECT_TYPE); 854 __ CompareObjectType(lhs, r6, r6, FIRST_SPEC_OBJECT_TYPE);
833 __ b(ge, &return_not_equal); 855 __ bge(&return_not_equal);
834 856
835 // Check for oddballs: true, false, null, undefined. 857 // Check for oddballs: true, false, null, undefined.
836 __ cmp(r3, Operand(ODDBALL_TYPE)); 858 __ cmpi(r6, Operand(ODDBALL_TYPE));
837 __ b(eq, &return_not_equal); 859 __ beq(&return_not_equal);
838 860
839 // Now that we have the types we might as well check for 861 // Now that we have the types we might as well check for
840 // internalized-internalized. 862 // internalized-internalized.
841 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 863 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
842 __ orr(r2, r2, Operand(r3)); 864 __ orx(r5, r5, r6);
843 __ tst(r2, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 865 __ andi(r0, r5, Operand(kIsNotStringMask | kIsNotInternalizedMask));
844 __ b(eq, &return_not_equal); 866 __ beq(&return_not_equal, cr0);
845 } 867 }
846 868
847 869
848 // See comment at call site. 870 // See comment at call site.
849 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, 871 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
850 Register lhs, 872 Register lhs,
851 Register rhs, 873 Register rhs,
852 Label* both_loaded_as_doubles, 874 Label* both_loaded_as_doubles,
853 Label* not_heap_numbers, 875 Label* not_heap_numbers,
854 Label* slow) { 876 Label* slow) {
855 ASSERT((lhs.is(r0) && rhs.is(r1)) || 877 ASSERT((lhs.is(r3) && rhs.is(r4)) ||
856 (lhs.is(r1) && rhs.is(r0))); 878 (lhs.is(r4) && rhs.is(r3)));
857 879
858 __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE); 880 __ CompareObjectType(rhs, r6, r5, HEAP_NUMBER_TYPE);
859 __ b(ne, not_heap_numbers); 881 __ bne(not_heap_numbers);
860 __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset)); 882 __ LoadP(r5, FieldMemOperand(lhs, HeapObject::kMapOffset));
861 __ cmp(r2, r3); 883 __ cmp(r5, r6);
862 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. 884 __ bne(slow); // First was a heap number, second wasn't. Go slow case.
863 885
864 // Both are heap numbers. Load them up then jump to the code we have 886 // Both are heap numbers. Load them up then jump to the code we have
865 // for that. 887 // for that.
866 __ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag); 888 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset));
867 __ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag); 889 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset));
868 __ jmp(both_loaded_as_doubles); 890
891 __ b(both_loaded_as_doubles);
869 } 892 }
870 893
871 894
872 // Fast negative check for internalized-to-internalized equality. 895 // Fast negative check for internalized-to-internalized equality.
873 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm, 896 static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
874 Register lhs, 897 Register lhs,
875 Register rhs, 898 Register rhs,
876 Label* possible_strings, 899 Label* possible_strings,
877 Label* not_both_strings) { 900 Label* not_both_strings) {
878 ASSERT((lhs.is(r0) && rhs.is(r1)) || 901 ASSERT((lhs.is(r3) && rhs.is(r4)) ||
879 (lhs.is(r1) && rhs.is(r0))); 902 (lhs.is(r4) && rhs.is(r3)));
880 903
881 // r2 is object type of rhs. 904 // r5 is object type of rhs.
882 Label object_test; 905 Label object_test;
883 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 906 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
884 __ tst(r2, Operand(kIsNotStringMask)); 907 __ andi(r0, r5, Operand(kIsNotStringMask));
885 __ b(ne, &object_test); 908 __ bne(&object_test, cr0);
886 __ tst(r2, Operand(kIsNotInternalizedMask)); 909 __ andi(r0, r5, Operand(kIsNotInternalizedMask));
887 __ b(ne, possible_strings); 910 __ bne(possible_strings, cr0);
888 __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE); 911 __ CompareObjectType(lhs, r6, r6, FIRST_NONSTRING_TYPE);
889 __ b(ge, not_both_strings); 912 __ bge(not_both_strings);
890 __ tst(r3, Operand(kIsNotInternalizedMask)); 913 __ andi(r0, r6, Operand(kIsNotInternalizedMask));
891 __ b(ne, possible_strings); 914 __ bne(possible_strings, cr0);
892 915
893 // Both are internalized. We already checked they weren't the same pointer 916 // Both are internalized. We already checked they weren't the same pointer
894 // so they are not equal. 917 // so they are not equal.
895 __ mov(r0, Operand(NOT_EQUAL)); 918 __ li(r3, Operand(NOT_EQUAL));
896 __ Ret(); 919 __ Ret();
897 920
898 __ bind(&object_test); 921 __ bind(&object_test);
899 __ cmp(r2, Operand(FIRST_SPEC_OBJECT_TYPE)); 922 __ cmpi(r5, Operand(FIRST_SPEC_OBJECT_TYPE));
900 __ b(lt, not_both_strings); 923 __ blt(not_both_strings);
901 __ CompareObjectType(lhs, r2, r3, FIRST_SPEC_OBJECT_TYPE); 924 __ CompareObjectType(lhs, r5, r6, FIRST_SPEC_OBJECT_TYPE);
902 __ b(lt, not_both_strings); 925 __ blt(not_both_strings);
903 // If both objects are undetectable, they are equal. Otherwise, they 926 // If both objects are undetectable, they are equal. Otherwise, they
904 // are not equal, since they are different objects and an object is not 927 // are not equal, since they are different objects and an object is not
905 // equal to undefined. 928 // equal to undefined.
906 __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset)); 929 __ LoadP(r6, FieldMemOperand(rhs, HeapObject::kMapOffset));
907 __ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset)); 930 __ lbz(r5, FieldMemOperand(r5, Map::kBitFieldOffset));
908 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); 931 __ lbz(r6, FieldMemOperand(r6, Map::kBitFieldOffset));
909 __ and_(r0, r2, Operand(r3)); 932 __ and_(r3, r5, r6);
910 __ and_(r0, r0, Operand(1 << Map::kIsUndetectable)); 933 __ andi(r3, r3, Operand(1 << Map::kIsUndetectable));
911 __ eor(r0, r0, Operand(1 << Map::kIsUndetectable)); 934 __ xori(r3, r3, Operand(1 << Map::kIsUndetectable));
912 __ Ret(); 935 __ Ret();
913 } 936 }
914 937
915 938
916 static void ICCompareStub_CheckInputType(MacroAssembler* masm, 939 static void ICCompareStub_CheckInputType(MacroAssembler* masm,
917 Register input, 940 Register input,
918 Register scratch, 941 Register scratch,
919 CompareIC::State expected, 942 CompareIC::State expected,
920 Label* fail) { 943 Label* fail) {
921 Label ok; 944 Label ok;
922 if (expected == CompareIC::SMI) { 945 if (expected == CompareIC::SMI) {
923 __ JumpIfNotSmi(input, fail); 946 __ JumpIfNotSmi(input, fail);
924 } else if (expected == CompareIC::NUMBER) { 947 } else if (expected == CompareIC::NUMBER) {
925 __ JumpIfSmi(input, &ok); 948 __ JumpIfSmi(input, &ok);
926 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail, 949 __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
927 DONT_DO_SMI_CHECK); 950 DONT_DO_SMI_CHECK);
928 } 951 }
929 // We could be strict about internalized/non-internalized here, but as long as 952 // We could be strict about internalized/non-internalized here, but as long as
930 // hydrogen doesn't care, the stub doesn't have to care either. 953 // hydrogen doesn't care, the stub doesn't have to care either.
931 __ bind(&ok); 954 __ bind(&ok);
932 } 955 }
933 956
934 957
935 // On entry r1 and r2 are the values to be compared. 958 // On entry r4 and r5 are the values to be compared.
936 // On exit r0 is 0, positive or negative to indicate the result of 959 // On exit r3 is 0, positive or negative to indicate the result of
937 // the comparison. 960 // the comparison.
938 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { 961 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
939 Register lhs = r1; 962 Register lhs = r4;
940 Register rhs = r0; 963 Register rhs = r3;
941 Condition cc = GetCondition(); 964 Condition cc = GetCondition();
942 965
943 Label miss; 966 Label miss;
944 ICCompareStub_CheckInputType(masm, lhs, r2, left_, &miss); 967 ICCompareStub_CheckInputType(masm, lhs, r5, left_, &miss);
945 ICCompareStub_CheckInputType(masm, rhs, r3, right_, &miss); 968 ICCompareStub_CheckInputType(masm, rhs, r6, right_, &miss);
946 969
947 Label slow; // Call builtin. 970 Label slow; // Call builtin.
948 Label not_smis, both_loaded_as_doubles, lhs_not_nan; 971 Label not_smis, both_loaded_as_doubles, lhs_not_nan;
949 972
950 Label not_two_smis, smi_done; 973 Label not_two_smis, smi_done;
951 __ orr(r2, r1, r0); 974 __ orx(r5, r4, r3);
952 __ JumpIfNotSmi(r2, &not_two_smis); 975 __ JumpIfNotSmi(r5, &not_two_smis);
953 __ mov(r1, Operand(r1, ASR, 1)); 976 __ SmiUntag(r4);
954 __ sub(r0, r1, Operand(r0, ASR, 1)); 977 __ SmiUntag(r3);
978 __ sub(r3, r4, r3);
955 __ Ret(); 979 __ Ret();
956 __ bind(&not_two_smis); 980 __ bind(&not_two_smis);
957 981
958 // NOTICE! This code is only reached after a smi-fast-case check, so 982 // NOTICE! This code is only reached after a smi-fast-case check, so
959 // it is certain that at least one operand isn't a smi. 983 // it is certain that at least one operand isn't a smi.
960 984
961 // Handle the case where the objects are identical. Either returns the answer 985 // Handle the case where the objects are identical. Either returns the answer
962 // or goes to slow. Only falls through if the objects were not identical. 986 // or goes to slow. Only falls through if the objects were not identical.
963 EmitIdenticalObjectComparison(masm, &slow, cc); 987 EmitIdenticalObjectComparison(masm, &slow, cc);
964 988
965 // If either is a Smi (we know that not both are), then they can only 989 // If either is a Smi (we know that not both are), then they can only
966 // be strictly equal if the other is a HeapNumber. 990 // be strictly equal if the other is a HeapNumber.
967 STATIC_ASSERT(kSmiTag == 0); 991 STATIC_ASSERT(kSmiTag == 0);
968 ASSERT_EQ(0, Smi::FromInt(0)); 992 ASSERT_EQ(0, Smi::FromInt(0));
969 __ and_(r2, lhs, Operand(rhs)); 993 __ and_(r5, lhs, rhs);
970 __ JumpIfNotSmi(r2, &not_smis); 994 __ JumpIfNotSmi(r5, &not_smis);
971 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 995 // One operand is a smi. EmitSmiNonsmiComparison generates code that can:
972 // 1) Return the answer. 996 // 1) Return the answer.
973 // 2) Go to slow. 997 // 2) Go to slow.
974 // 3) Fall through to both_loaded_as_doubles. 998 // 3) Fall through to both_loaded_as_doubles.
975 // 4) Jump to lhs_not_nan. 999 // 4) Jump to lhs_not_nan.
976 // In cases 3 and 4 we have found out we were dealing with a number-number 1000 // In cases 3 and 4 we have found out we were dealing with a number-number
977 // comparison. If VFP3 is supported the double values of the numbers have 1001 // comparison. The double values of the numbers have been loaded
978 // been loaded into d7 and d6. Otherwise, the double values have been loaded 1002 // into d7 and d6.
979 // into r0, r1, r2, and r3.
980 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict()); 1003 EmitSmiNonsmiComparison(masm, lhs, rhs, &lhs_not_nan, &slow, strict());
981 1004
982 __ bind(&both_loaded_as_doubles); 1005 __ bind(&both_loaded_as_doubles);
983 // The arguments have been converted to doubles and stored in d6 and d7, if 1006 // The arguments have been converted to doubles and stored in d6 and d7
984 // VFP3 is supported, or in r0, r1, r2, and r3.
985 __ bind(&lhs_not_nan); 1007 __ bind(&lhs_not_nan);
986 Label no_nan; 1008 Label no_nan;
987 // ARMv7 VFP3 instructions to implement double precision comparison. 1009 __ fcmpu(d7, d6);
988 __ VFPCompareAndSetFlags(d7, d6); 1010
989 Label nan; 1011 Label nan, equal, less_than;
990 __ b(vs, &nan); 1012 __ bunordered(&nan);
991 __ mov(r0, Operand(EQUAL), LeaveCC, eq); 1013 __ beq(&equal);
992 __ mov(r0, Operand(LESS), LeaveCC, lt); 1014 __ blt(&less_than);
993 __ mov(r0, Operand(GREATER), LeaveCC, gt); 1015 __ li(r3, Operand(GREATER));
1016 __ Ret();
1017 __ bind(&equal);
1018 __ li(r3, Operand(EQUAL));
1019 __ Ret();
1020 __ bind(&less_than);
1021 __ li(r3, Operand(LESS));
994 __ Ret(); 1022 __ Ret();
995 1023
996 __ bind(&nan); 1024 __ bind(&nan);
997 // If one of the sides was a NaN then the v flag is set. Load r0 with 1025 // If one of the sides was a NaN then the v flag is set. Load r3 with
998 // whatever it takes to make the comparison fail, since comparisons with NaN 1026 // whatever it takes to make the comparison fail, since comparisons with NaN
999 // always fail. 1027 // always fail.
1000 if (cc == lt || cc == le) { 1028 if (cc == lt || cc == le) {
1001 __ mov(r0, Operand(GREATER)); 1029 __ li(r3, Operand(GREATER));
1002 } else { 1030 } else {
1003 __ mov(r0, Operand(LESS)); 1031 __ li(r3, Operand(LESS));
1004 } 1032 }
1005 __ Ret(); 1033 __ Ret();
1006 1034
1007 __ bind(&not_smis); 1035 __ bind(&not_smis);
1008 // At this point we know we are dealing with two different objects, 1036 // At this point we know we are dealing with two different objects,
1009 // and neither of them is a Smi. The objects are in rhs_ and lhs_. 1037 // and neither of them is a Smi. The objects are in rhs_ and lhs_.
1010 if (strict()) { 1038 if (strict()) {
1011 // This returns non-equal for some object types, or falls through if it 1039 // This returns non-equal for some object types, or falls through if it
1012 // was not lucky. 1040 // was not lucky.
1013 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs); 1041 EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
1014 } 1042 }
1015 1043
1016 Label check_for_internalized_strings; 1044 Label check_for_internalized_strings;
1017 Label flat_string_check; 1045 Label flat_string_check;
1018 // Check for heap-number-heap-number comparison. Can jump to slow case, 1046 // Check for heap-number-heap-number comparison. Can jump to slow case,
1019 // or load both doubles into r0, r1, r2, r3 and jump to the code that handles 1047 // or load both doubles into r3, r4, r5, r6 and jump to the code that handles
1020 // that case. If the inputs are not doubles then jumps to 1048 // that case. If the inputs are not doubles then jumps to
1021 // check_for_internalized_strings. 1049 // check_for_internalized_strings.
1022 // In this case r2 will contain the type of rhs_. Never falls through. 1050 // In this case r5 will contain the type of rhs_. Never falls through.
1023 EmitCheckForTwoHeapNumbers(masm, 1051 EmitCheckForTwoHeapNumbers(masm,
1024 lhs, 1052 lhs,
1025 rhs, 1053 rhs,
1026 &both_loaded_as_doubles, 1054 &both_loaded_as_doubles,
1027 &check_for_internalized_strings, 1055 &check_for_internalized_strings,
1028 &flat_string_check); 1056 &flat_string_check);
1029 1057
1030 __ bind(&check_for_internalized_strings); 1058 __ bind(&check_for_internalized_strings);
1031 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of 1059 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
1032 // internalized strings. 1060 // internalized strings.
1033 if (cc == eq && !strict()) { 1061 if (cc == eq && !strict()) {
1034 // Returns an answer for two internalized strings or two detectable objects. 1062 // Returns an answer for two internalized strings or two detectable objects.
1035 // Otherwise jumps to string case or not both strings case. 1063 // Otherwise jumps to string case or not both strings case.
1036 // Assumes that r2 is the type of rhs_ on entry. 1064 // Assumes that r5 is the type of rhs_ on entry.
1037 EmitCheckForInternalizedStringsOrObjects( 1065 EmitCheckForInternalizedStringsOrObjects(
1038 masm, lhs, rhs, &flat_string_check, &slow); 1066 masm, lhs, rhs, &flat_string_check, &slow);
1039 } 1067 }
1040 1068
1041 // Check for both being sequential ASCII strings, and inline if that is the 1069 // Check for both being sequential ASCII strings, and inline if that is the
1042 // case. 1070 // case.
1043 __ bind(&flat_string_check); 1071 __ bind(&flat_string_check);
1044 1072
1045 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, r2, r3, &slow); 1073 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, r5, r6, &slow);
1046 1074
1047 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r2, 1075 __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r5,
1048 r3); 1076 r6);
1049 if (cc == eq) { 1077 if (cc == eq) {
1050 StringCompareStub::GenerateFlatAsciiStringEquals(masm, 1078 StringCompareStub::GenerateFlatAsciiStringEquals(masm,
1051 lhs, 1079 lhs,
1052 rhs, 1080 rhs,
1053 r2, 1081 r5,
1054 r3, 1082 r6);
1055 r4);
1056 } else { 1083 } else {
1057 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 1084 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
1058 lhs, 1085 lhs,
1059 rhs, 1086 rhs,
1060 r2, 1087 r5,
1061 r3, 1088 r6,
1062 r4, 1089 r7);
1063 r5);
1064 } 1090 }
1065 // Never falls through to here. 1091 // Never falls through to here.
1066 1092
1067 __ bind(&slow); 1093 __ bind(&slow);
1068 1094
1069 __ Push(lhs, rhs); 1095 __ Push(lhs, rhs);
1070 // Figure out which native to call and setup the arguments. 1096 // Figure out which native to call and setup the arguments.
1071 Builtins::JavaScript native; 1097 Builtins::JavaScript native;
1072 if (cc == eq) { 1098 if (cc == eq) {
1073 native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 1099 native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
1074 } else { 1100 } else {
1075 native = Builtins::COMPARE; 1101 native = Builtins::COMPARE;
1076 int ncr; // NaN compare result 1102 int ncr; // NaN compare result
1077 if (cc == lt || cc == le) { 1103 if (cc == lt || cc == le) {
1078 ncr = GREATER; 1104 ncr = GREATER;
1079 } else { 1105 } else {
1080 ASSERT(cc == gt || cc == ge); // remaining cases 1106 ASSERT(cc == gt || cc == ge); // remaining cases
1081 ncr = LESS; 1107 ncr = LESS;
1082 } 1108 }
1083 __ mov(r0, Operand(Smi::FromInt(ncr))); 1109 __ LoadSmiLiteral(r3, Smi::FromInt(ncr));
1084 __ push(r0); 1110 __ push(r3);
1085 } 1111 }
1086 1112
1087 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 1113 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
1088 // tagged as a small integer. 1114 // tagged as a small integer.
1089 __ InvokeBuiltin(native, JUMP_FUNCTION); 1115 __ InvokeBuiltin(native, JUMP_FUNCTION);
1090 1116
1091 __ bind(&miss); 1117 __ bind(&miss);
1092 GenerateMiss(masm); 1118 GenerateMiss(masm);
1093 } 1119 }
1094 1120
1095 1121
1096 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 1122 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
1097 // We don't allow a GC during a store buffer overflow so there is no need to 1123 // We don't allow a GC during a store buffer overflow so there is no need to
1098 // store the registers in any particular way, but we do have to store and 1124 // store the registers in any particular way, but we do have to store and
1099 // restore them. 1125 // restore them.
1100 __ stm(db_w, sp, kCallerSaved | lr.bit()); 1126 __ mflr(r0);
1101 1127 __ MultiPush(kJSCallerSaved | r0.bit());
1102 const Register scratch = r1;
1103
1104 if (save_doubles_ == kSaveFPRegs) { 1128 if (save_doubles_ == kSaveFPRegs) {
1105 __ SaveFPRegs(sp, scratch); 1129 __ SaveFPRegs(sp, 0, DoubleRegister::kNumVolatileRegisters);
1106 } 1130 }
1107 const int argument_count = 1; 1131 const int argument_count = 1;
1108 const int fp_argument_count = 0; 1132 const int fp_argument_count = 0;
1133 const Register scratch = r4;
1109 1134
1110 AllowExternalCallThatCantCauseGC scope(masm); 1135 AllowExternalCallThatCantCauseGC scope(masm);
1111 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch); 1136 __ PrepareCallCFunction(argument_count, fp_argument_count, scratch);
1112 __ mov(r0, Operand(ExternalReference::isolate_address(isolate()))); 1137 __ mov(r3, Operand(ExternalReference::isolate_address(isolate())));
1113 __ CallCFunction( 1138 __ CallCFunction(
1114 ExternalReference::store_buffer_overflow_function(isolate()), 1139 ExternalReference::store_buffer_overflow_function(isolate()),
1115 argument_count); 1140 argument_count);
1116 if (save_doubles_ == kSaveFPRegs) { 1141 if (save_doubles_ == kSaveFPRegs) {
1117 __ RestoreFPRegs(sp, scratch); 1142 __ RestoreFPRegs(sp, 0, DoubleRegister::kNumVolatileRegisters);
1118 } 1143 }
1119 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). 1144 __ MultiPop(kJSCallerSaved | r0.bit());
1145 __ mtlr(r0);
1146 __ Ret();
1120 } 1147 }
1121 1148
1122 1149
1123 void MathPowStub::Generate(MacroAssembler* masm) { 1150 void MathPowStub::Generate(MacroAssembler* masm) {
1124 const Register base = r1; 1151 const Register base = r4;
1125 const Register exponent = r2; 1152 const Register exponent = r5;
1126 const Register heapnumbermap = r5; 1153 const Register heapnumbermap = r8;
1127 const Register heapnumber = r0; 1154 const Register heapnumber = r3;
1128 const DwVfpRegister double_base = d0; 1155 const DoubleRegister double_base = d1;
1129 const DwVfpRegister double_exponent = d1; 1156 const DoubleRegister double_exponent = d2;
1130 const DwVfpRegister double_result = d2; 1157 const DoubleRegister double_result = d3;
1131 const DwVfpRegister double_scratch = d3; 1158 const DoubleRegister double_scratch = d0;
1132 const SwVfpRegister single_scratch = s6; 1159 const Register scratch = r11;
1133 const Register scratch = r9; 1160 const Register scratch2 = r10;
1134 const Register scratch2 = r4;
1135 1161
1136 Label call_runtime, done, int_exponent; 1162 Label call_runtime, done, int_exponent;
1137 if (exponent_type_ == ON_STACK) { 1163 if (exponent_type_ == ON_STACK) {
1138 Label base_is_smi, unpack_exponent; 1164 Label base_is_smi, unpack_exponent;
1139 // The exponent and base are supplied as arguments on the stack. 1165 // The exponent and base are supplied as arguments on the stack.
1140 // This can only happen if the stub is called from non-optimized code. 1166 // This can only happen if the stub is called from non-optimized code.
1141 // Load input parameters from stack to double registers. 1167 // Load input parameters from stack to double registers.
1142 __ ldr(base, MemOperand(sp, 1 * kPointerSize)); 1168 __ LoadP(base, MemOperand(sp, 1 * kPointerSize));
1143 __ ldr(exponent, MemOperand(sp, 0 * kPointerSize)); 1169 __ LoadP(exponent, MemOperand(sp, 0 * kPointerSize));
1144 1170
1145 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); 1171 __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex);
1146 1172
1147 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi); 1173 __ UntagAndJumpIfSmi(scratch, base, &base_is_smi);
1148 __ ldr(scratch, FieldMemOperand(base, JSObject::kMapOffset)); 1174 __ LoadP(scratch, FieldMemOperand(base, JSObject::kMapOffset));
1149 __ cmp(scratch, heapnumbermap); 1175 __ cmp(scratch, heapnumbermap);
1150 __ b(ne, &call_runtime); 1176 __ bne(&call_runtime);
1151 1177
1152 __ vldr(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); 1178 __ lfd(double_base, FieldMemOperand(base, HeapNumber::kValueOffset));
1153 __ jmp(&unpack_exponent); 1179 __ b(&unpack_exponent);
1154 1180
1155 __ bind(&base_is_smi); 1181 __ bind(&base_is_smi);
1156 __ vmov(single_scratch, scratch); 1182 __ ConvertIntToDouble(scratch, double_base);
1157 __ vcvt_f64_s32(double_base, single_scratch);
1158 __ bind(&unpack_exponent); 1183 __ bind(&unpack_exponent);
1159 1184
1160 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 1185 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
1186 __ LoadP(scratch, FieldMemOperand(exponent, JSObject::kMapOffset));
1187 __ cmp(scratch, heapnumbermap);
1188 __ bne(&call_runtime);
1161 1189
1162 __ ldr(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); 1190 __ lfd(double_exponent,
1163 __ cmp(scratch, heapnumbermap); 1191 FieldMemOperand(exponent, HeapNumber::kValueOffset));
1164 __ b(ne, &call_runtime);
1165 __ vldr(double_exponent,
1166 FieldMemOperand(exponent, HeapNumber::kValueOffset));
1167 } else if (exponent_type_ == TAGGED) { 1192 } else if (exponent_type_ == TAGGED) {
1168 // Base is already in double_base. 1193 // Base is already in double_base.
1169 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent); 1194 __ UntagAndJumpIfSmi(scratch, exponent, &int_exponent);
1170 1195
1171 __ vldr(double_exponent, 1196 __ lfd(double_exponent,
1172 FieldMemOperand(exponent, HeapNumber::kValueOffset)); 1197 FieldMemOperand(exponent, HeapNumber::kValueOffset));
1173 } 1198 }
1174 1199
1175 if (exponent_type_ != INTEGER) { 1200 if (exponent_type_ != INTEGER) {
1176 Label int_exponent_convert;
1177 // Detect integer exponents stored as double. 1201 // Detect integer exponents stored as double.
1178 __ vcvt_u32_f64(single_scratch, double_exponent); 1202 __ TryDoubleToInt32Exact(scratch, double_exponent,
1179 // We do not check for NaN or Infinity here because comparing numbers on 1203 scratch2, double_scratch);
1180 // ARM correctly distinguishes NaNs. We end up calling the built-in. 1204 __ beq(&int_exponent);
1181 __ vcvt_f64_u32(double_scratch, single_scratch);
1182 __ VFPCompareAndSetFlags(double_scratch, double_exponent);
1183 __ b(eq, &int_exponent_convert);
1184 1205
1185 if (exponent_type_ == ON_STACK) { 1206 if (exponent_type_ == ON_STACK) {
1186 // Detect square root case. Crankshaft detects constant +/-0.5 at 1207 // Detect square root case. Crankshaft detects constant +/-0.5 at
1187 // compile time and uses DoMathPowHalf instead. We then skip this check 1208 // compile time and uses DoMathPowHalf instead. We then skip this check
1188 // for non-constant cases of +/-0.5 as these hardly occur. 1209 // for non-constant cases of +/-0.5 as these hardly occur.
1189 Label not_plus_half; 1210 Label not_plus_half, not_minus_inf1, not_minus_inf2;
1190 1211
1191 // Test for 0.5. 1212 // Test for 0.5.
1192 __ vmov(double_scratch, 0.5, scratch); 1213 __ LoadDoubleLiteral(double_scratch, 0.5, scratch);
1193 __ VFPCompareAndSetFlags(double_exponent, double_scratch); 1214 __ fcmpu(double_exponent, double_scratch);
1194 __ b(ne, &not_plus_half); 1215 __ bne(&not_plus_half);
1195 1216
1196 // Calculates square root of base. Check for the special case of 1217 // Calculates square root of base. Check for the special case of
1197 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). 1218 // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
1198 __ vmov(double_scratch, -V8_INFINITY, scratch); 1219 __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch);
1199 __ VFPCompareAndSetFlags(double_base, double_scratch); 1220 __ fcmpu(double_base, double_scratch);
1200 __ vneg(double_result, double_scratch, eq); 1221 __ bne(&not_minus_inf1);
1201 __ b(eq, &done); 1222 __ fneg(double_result, double_scratch);
1223 __ b(&done);
1224 __ bind(&not_minus_inf1);
1202 1225
1203 // Add +0 to convert -0 to +0. 1226 // Add +0 to convert -0 to +0.
1204 __ vadd(double_scratch, double_base, kDoubleRegZero); 1227 __ fadd(double_scratch, double_base, kDoubleRegZero);
1205 __ vsqrt(double_result, double_scratch); 1228 __ fsqrt(double_result, double_scratch);
1206 __ jmp(&done); 1229 __ b(&done);
1207 1230
1208 __ bind(&not_plus_half); 1231 __ bind(&not_plus_half);
1209 __ vmov(double_scratch, -0.5, scratch); 1232 __ LoadDoubleLiteral(double_scratch, -0.5, scratch);
1210 __ VFPCompareAndSetFlags(double_exponent, double_scratch); 1233 __ fcmpu(double_exponent, double_scratch);
1211 __ b(ne, &call_runtime); 1234 __ bne(&call_runtime);
1212 1235
1213 // Calculates square root of base. Check for the special case of 1236 // Calculates square root of base. Check for the special case of
1214 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). 1237 // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
1215 __ vmov(double_scratch, -V8_INFINITY, scratch); 1238 __ LoadDoubleLiteral(double_scratch, -V8_INFINITY, scratch);
1216 __ VFPCompareAndSetFlags(double_base, double_scratch); 1239 __ fcmpu(double_base, double_scratch);
1217 __ vmov(double_result, kDoubleRegZero, eq); 1240 __ bne(&not_minus_inf2);
1218 __ b(eq, &done); 1241 __ fmr(double_result, kDoubleRegZero);
1242 __ b(&done);
1243 __ bind(&not_minus_inf2);
1219 1244
1220 // Add +0 to convert -0 to +0. 1245 // Add +0 to convert -0 to +0.
1221 __ vadd(double_scratch, double_base, kDoubleRegZero); 1246 __ fadd(double_scratch, double_base, kDoubleRegZero);
1222 __ vmov(double_result, 1.0, scratch); 1247 __ LoadDoubleLiteral(double_result, 1.0, scratch);
1223 __ vsqrt(double_scratch, double_scratch); 1248 __ fsqrt(double_scratch, double_scratch);
1224 __ vdiv(double_result, double_result, double_scratch); 1249 __ fdiv(double_result, double_result, double_scratch);
1225 __ jmp(&done); 1250 __ b(&done);
1226 } 1251 }
1227 1252
1228 __ push(lr); 1253 __ mflr(r0);
1254 __ push(r0);
1229 { 1255 {
1230 AllowExternalCallThatCantCauseGC scope(masm); 1256 AllowExternalCallThatCantCauseGC scope(masm);
1231 __ PrepareCallCFunction(0, 2, scratch); 1257 __ PrepareCallCFunction(0, 2, scratch);
1232 __ MovToFloatParameters(double_base, double_exponent); 1258 __ MovToFloatParameters(double_base, double_exponent);
1233 __ CallCFunction( 1259 __ CallCFunction(
1234 ExternalReference::power_double_double_function(isolate()), 1260 ExternalReference::power_double_double_function(isolate()),
1235 0, 2); 1261 0, 2);
1236 } 1262 }
1237 __ pop(lr); 1263 __ pop(r0);
1264 __ mtlr(r0);
1238 __ MovFromFloatResult(double_result); 1265 __ MovFromFloatResult(double_result);
1239 __ jmp(&done); 1266 __ b(&done);
1240
1241 __ bind(&int_exponent_convert);
1242 __ vcvt_u32_f64(single_scratch, double_exponent);
1243 __ vmov(scratch, single_scratch);
1244 } 1267 }
1245 1268
1246 // Calculate power with integer exponent. 1269 // Calculate power with integer exponent.
1247 __ bind(&int_exponent); 1270 __ bind(&int_exponent);
1248 1271
1249 // Get two copies of exponent in the registers scratch and exponent. 1272 // Get two copies of exponent in the registers scratch and exponent.
1250 if (exponent_type_ == INTEGER) { 1273 if (exponent_type_ == INTEGER) {
1251 __ mov(scratch, exponent); 1274 __ mr(scratch, exponent);
1252 } else { 1275 } else {
1253 // Exponent has previously been stored into scratch as untagged integer. 1276 // Exponent has previously been stored into scratch as untagged integer.
1254 __ mov(exponent, scratch); 1277 __ mr(exponent, scratch);
1255 } 1278 }
1256 __ vmov(double_scratch, double_base); // Back up base. 1279 __ fmr(double_scratch, double_base); // Back up base.
1257 __ vmov(double_result, 1.0, scratch2); 1280 __ li(scratch2, Operand(1));
1281 __ ConvertIntToDouble(scratch2, double_result);
1258 1282
1259 // Get absolute value of exponent. 1283 // Get absolute value of exponent.
1260 __ cmp(scratch, Operand::Zero()); 1284 Label positive_exponent;
1261 __ mov(scratch2, Operand::Zero(), LeaveCC, mi); 1285 __ cmpi(scratch, Operand::Zero());
1262 __ sub(scratch, scratch2, scratch, LeaveCC, mi); 1286 __ bge(&positive_exponent);
1287 __ neg(scratch, scratch);
1288 __ bind(&positive_exponent);
1263 1289
1264 Label while_true; 1290 Label while_true, no_carry, loop_end;
1265 __ bind(&while_true); 1291 __ bind(&while_true);
1266 __ mov(scratch, Operand(scratch, ASR, 1), SetCC); 1292 __ andi(scratch2, scratch, Operand(1));
1267 __ vmul(double_result, double_result, double_scratch, cs); 1293 __ beq(&no_carry, cr0);
1268 __ vmul(double_scratch, double_scratch, double_scratch, ne); 1294 __ fmul(double_result, double_result, double_scratch);
1269 __ b(ne, &while_true); 1295 __ bind(&no_carry);
1296 __ ShiftRightArithImm(scratch, scratch, 1, SetRC);
1297 __ beq(&loop_end, cr0);
1298 __ fmul(double_scratch, double_scratch, double_scratch);
1299 __ b(&while_true);
1300 __ bind(&loop_end);
1270 1301
1271 __ cmp(exponent, Operand::Zero()); 1302 __ cmpi(exponent, Operand::Zero());
1272 __ b(ge, &done); 1303 __ bge(&done);
1273 __ vmov(double_scratch, 1.0, scratch); 1304
1274 __ vdiv(double_result, double_scratch, double_result); 1305 __ li(scratch2, Operand(1));
1306 __ ConvertIntToDouble(scratch2, double_scratch);
1307 __ fdiv(double_result, double_scratch, double_result);
1275 // Test whether result is zero. Bail out to check for subnormal result. 1308 // Test whether result is zero. Bail out to check for subnormal result.
1276 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. 1309 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
1277 __ VFPCompareAndSetFlags(double_result, 0.0); 1310 __ fcmpu(double_result, kDoubleRegZero);
1278 __ b(ne, &done); 1311 __ bne(&done);
1279 // double_exponent may not containe the exponent value if the input was a 1312 // double_exponent may not containe the exponent value if the input was a
1280 // smi. We set it with exponent value before bailing out. 1313 // smi. We set it with exponent value before bailing out.
1281 __ vmov(single_scratch, exponent); 1314 __ ConvertIntToDouble(exponent, double_exponent);
1282 __ vcvt_f64_s32(double_exponent, single_scratch);
1283 1315
1284 // Returning or bailing out. 1316 // Returning or bailing out.
1285 Counters* counters = isolate()->counters(); 1317 Counters* counters = isolate()->counters();
1286 if (exponent_type_ == ON_STACK) { 1318 if (exponent_type_ == ON_STACK) {
1287 // The arguments are still on the stack. 1319 // The arguments are still on the stack.
1288 __ bind(&call_runtime); 1320 __ bind(&call_runtime);
1289 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1); 1321 __ TailCallRuntime(Runtime::kMathPowRT, 2, 1);
1290 1322
1291 // The stub is called from non-optimized code, which expects the result 1323 // The stub is called from non-optimized code, which expects the result
1292 // as heap number in exponent. 1324 // as heap number in exponent.
1293 __ bind(&done); 1325 __ bind(&done);
1294 __ AllocateHeapNumber( 1326 __ AllocateHeapNumber(
1295 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); 1327 heapnumber, scratch, scratch2, heapnumbermap, &call_runtime);
1296 __ vstr(double_result, 1328 __ stfd(double_result,
1297 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); 1329 FieldMemOperand(heapnumber, HeapNumber::kValueOffset));
1298 ASSERT(heapnumber.is(r0)); 1330 ASSERT(heapnumber.is(r3));
1299 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 1331 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
1300 __ Ret(2); 1332 __ Ret(2);
1301 } else { 1333 } else {
1302 __ push(lr); 1334 __ mflr(r0);
1335 __ push(r0);
1303 { 1336 {
1304 AllowExternalCallThatCantCauseGC scope(masm); 1337 AllowExternalCallThatCantCauseGC scope(masm);
1305 __ PrepareCallCFunction(0, 2, scratch); 1338 __ PrepareCallCFunction(0, 2, scratch);
1306 __ MovToFloatParameters(double_base, double_exponent); 1339 __ MovToFloatParameters(double_base, double_exponent);
1307 __ CallCFunction( 1340 __ CallCFunction(
1308 ExternalReference::power_double_double_function(isolate()), 1341 ExternalReference::power_double_double_function(isolate()),
1309 0, 2); 1342 0, 2);
1310 } 1343 }
1311 __ pop(lr); 1344 __ pop(r0);
1345 __ mtlr(r0);
1312 __ MovFromFloatResult(double_result); 1346 __ MovFromFloatResult(double_result);
1313 1347
1314 __ bind(&done); 1348 __ bind(&done);
1315 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); 1349 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
1316 __ Ret(); 1350 __ Ret();
1317 } 1351 }
1318 } 1352 }
1319 1353
1320 1354
1321 bool CEntryStub::NeedsImmovableCode() { 1355 bool CEntryStub::NeedsImmovableCode() {
1322 return true; 1356 return true;
1323 } 1357 }
1324 1358
1325 1359
1326 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 1360 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
1327 CEntryStub::GenerateAheadOfTime(isolate); 1361 CEntryStub::GenerateAheadOfTime(isolate);
1328 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); 1362 // WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate);
1329 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 1363 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
1330 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 1364 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
1331 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 1365 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1332 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 1366 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
1333 BinaryOpICStub::GenerateAheadOfTime(isolate); 1367 BinaryOpICStub::GenerateAheadOfTime(isolate);
1334 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); 1368 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
1335 } 1369 }
1336 1370
1337 1371
1338 void CodeStub::GenerateFPStubs(Isolate* isolate) { 1372 void CodeStub::GenerateFPStubs(Isolate* isolate) {
(...skipping 16 matching lines...) Expand all
1355 1389
1356 1390
1357 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 1391 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
1358 CEntryStub stub(isolate, 1, kDontSaveFPRegs); 1392 CEntryStub stub(isolate, 1, kDontSaveFPRegs);
1359 stub.GetCode(); 1393 stub.GetCode();
1360 } 1394 }
1361 1395
1362 1396
1363 void CEntryStub::Generate(MacroAssembler* masm) { 1397 void CEntryStub::Generate(MacroAssembler* masm) {
1364 // Called from JavaScript; parameters are on stack as if calling JS function. 1398 // Called from JavaScript; parameters are on stack as if calling JS function.
1365 // r0: number of arguments including receiver 1399 // r3: number of arguments including receiver
1366 // r1: pointer to builtin function 1400 // r4: pointer to builtin function
1367 // fp: frame pointer (restored after C call) 1401 // fp: frame pointer (restored after C call)
1368 // sp: stack pointer (restored as callee's sp after C call) 1402 // sp: stack pointer (restored as callee's sp after C call)
1369 // cp: current context (C callee-saved) 1403 // cp: current context (C callee-saved)
1370 1404
1371 ProfileEntryHookStub::MaybeCallEntryHook(masm); 1405 ProfileEntryHookStub::MaybeCallEntryHook(masm);
1372 1406
1373 __ mov(r5, Operand(r1)); 1407 __ mr(r15, r4);
1374 1408
1375 // Compute the argv pointer in a callee-saved register. 1409 // Compute the argv pointer.
1376 __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2)); 1410 __ ShiftLeftImm(r4, r3, Operand(kPointerSizeLog2));
1377 __ sub(r1, r1, Operand(kPointerSize)); 1411 __ add(r4, r4, sp);
1412 __ subi(r4, r4, Operand(kPointerSize));
1378 1413
1379 // Enter the exit frame that transitions from JavaScript to C++. 1414 // Enter the exit frame that transitions from JavaScript to C++.
1380 FrameScope scope(masm, StackFrame::MANUAL); 1415 FrameScope scope(masm, StackFrame::MANUAL);
1381 __ EnterExitFrame(save_doubles_); 1416
1417 // Need at least one extra slot for return address location.
1418 int arg_stack_space = 1;
1419
1420 // PPC LINUX ABI:
1421 #if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
1422 // Pass buffer for return value on stack if necessary
1423 if (result_size_ > 1) {
1424 ASSERT_EQ(2, result_size_);
1425 arg_stack_space += 2;
1426 }
1427 #endif
1428
1429 __ EnterExitFrame(save_doubles_, arg_stack_space);
1382 1430
1383 // Store a copy of argc in callee-saved registers for later. 1431 // Store a copy of argc in callee-saved registers for later.
1384 __ mov(r4, Operand(r0)); 1432 __ mr(r14, r3);
1385 1433
1386 // r0, r4: number of arguments including receiver (C callee-saved) 1434 // r3, r14: number of arguments including receiver (C callee-saved)
1387 // r1: pointer to the first argument (C callee-saved) 1435 // r4: pointer to the first argument
1388 // r5: pointer to builtin function (C callee-saved) 1436 // r15: pointer to builtin function (C callee-saved)
1389 1437
1390 // Result returned in r0 or r0+r1 by default. 1438 // Result returned in registers or stack, depending on result size and ABI.
1391 1439
1392 #if V8_HOST_ARCH_ARM 1440 Register isolate_reg = r5;
1393 int frame_alignment = MacroAssembler::ActivationFrameAlignment(); 1441 #if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
1394 int frame_alignment_mask = frame_alignment - 1; 1442 if (result_size_ > 1) {
1395 if (FLAG_debug_code) { 1443 // The return value is 16-byte non-scalar value.
1396 if (frame_alignment > kPointerSize) { 1444 // Use frame storage reserved by calling function to pass return
1397 Label alignment_as_expected; 1445 // buffer as implicit first argument.
1398 ASSERT(IsPowerOf2(frame_alignment)); 1446 __ mr(r5, r4);
1399 __ tst(sp, Operand(frame_alignment_mask)); 1447 __ mr(r4, r3);
1400 __ b(eq, &alignment_as_expected); 1448 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
1401 // Don't use Check here, as it will call Runtime_Abort re-entering here. 1449 isolate_reg = r6;
1402 __ stop("Unexpected alignment");
1403 __ bind(&alignment_as_expected);
1404 }
1405 } 1450 }
1406 #endif 1451 #endif
1407 1452
1408 // Call C built-in. 1453 // Call C built-in.
1409 // r0 = argc, r1 = argv 1454 __ mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate())));
1410 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); 1455
1456 #if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
1457 // Native AIX/PPC64 Linux use a function descriptor.
1458 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
1459 __ LoadP(ip, MemOperand(r15, 0)); // Instruction address
1460 Register target = ip;
1461 #elif ABI_TOC_ADDRESSABILITY_VIA_IP
1462 __ Move(ip, r15);
1463 Register target = ip;
1464 #else
1465 Register target = r15;
1466 #endif
1411 1467
1412 // To let the GC traverse the return address of the exit frames, we need to 1468 // To let the GC traverse the return address of the exit frames, we need to
1413 // know where the return address is. The CEntryStub is unmovable, so 1469 // know where the return address is. The CEntryStub is unmovable, so
1414 // we can store the address on the stack to be able to find it again and 1470 // we can store the address on the stack to be able to find it again and
1415 // we never have to restore it, because it will not change. 1471 // we never have to restore it, because it will not change.
1416 // Compute the return address in lr to return to after the jump below. Pc is 1472 // Compute the return address in lr to return to after the jump below. Pc is
1417 // already at '+ 8' from the current instruction but return is after three 1473 // already at '+ 8' from the current instruction but return is after three
1418 // instructions so add another 4 to pc to get the return address. 1474 // instructions so add another 4 to pc to get the return address.
1419 { 1475 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
1420 // Prevent literal pool emission before return address. 1476 Label here;
1421 Assembler::BlockConstPoolScope block_const_pool(masm); 1477 __ b(&here, SetLK);
1422 __ add(lr, pc, Operand(4)); 1478 __ bind(&here);
1423 __ str(lr, MemOperand(sp, 0)); 1479 __ mflr(r8);
1424 __ Call(r5); 1480
1481 // Constant used below is dependent on size of Call() macro instructions
1482 __ addi(r0, r8, Operand(20));
1483
1484 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
1485 __ Call(target);
1425 } 1486 }
1426 1487
1427 __ VFPEnsureFPSCRState(r2); 1488 // roohack - do we need to (re)set FPU state?
1489
1490 #if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
1491 // If return value is on the stack, pop it to registers.
1492 if (result_size_ > 1) {
1493 __ LoadP(r4, MemOperand(r3, kPointerSize));
1494 __ LoadP(r3, MemOperand(r3));
1495 }
1496 #endif
1428 1497
1429 // Runtime functions should not return 'the hole'. Allowing it to escape may 1498 // Runtime functions should not return 'the hole'. Allowing it to escape may
1430 // lead to crashes in the IC code later. 1499 // lead to crashes in the IC code later.
1431 if (FLAG_debug_code) { 1500 if (FLAG_debug_code) {
1432 Label okay; 1501 Label okay;
1433 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 1502 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
1434 __ b(ne, &okay); 1503 __ bne(&okay);
1435 __ stop("The hole escaped"); 1504 __ stop("The hole escaped");
1436 __ bind(&okay); 1505 __ bind(&okay);
1437 } 1506 }
1438 1507
1439 // Check result for exception sentinel. 1508 // Check result for exception sentinel.
1440 Label exception_returned; 1509 Label exception_returned;
1441 __ CompareRoot(r0, Heap::kExceptionRootIndex); 1510 __ CompareRoot(r3, Heap::kExceptionRootIndex);
1442 __ b(eq, &exception_returned); 1511 __ beq(&exception_returned);
1443 1512
1444 ExternalReference pending_exception_address( 1513 ExternalReference pending_exception_address(
1445 Isolate::kPendingExceptionAddress, isolate()); 1514 Isolate::kPendingExceptionAddress, isolate());
1446 1515
1447 // Check that there is no pending exception, otherwise we 1516 // Check that there is no pending exception, otherwise we
1448 // should have returned the exception sentinel. 1517 // should have returned the exception sentinel.
1449 if (FLAG_debug_code) { 1518 if (FLAG_debug_code) {
1450 Label okay; 1519 Label okay;
1451 __ mov(r2, Operand(pending_exception_address)); 1520 __ mov(r5, Operand(pending_exception_address));
1452 __ ldr(r2, MemOperand(r2)); 1521 __ LoadP(r5, MemOperand(r5));
1453 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); 1522 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
1454 // Cannot use check here as it attempts to generate call into runtime. 1523 // Cannot use check here as it attempts to generate call into runtime.
1455 __ b(eq, &okay); 1524 __ beq(&okay);
1456 __ stop("Unexpected pending exception"); 1525 __ stop("Unexpected pending exception");
1457 __ bind(&okay); 1526 __ bind(&okay);
1458 } 1527 }
1459 1528
1460 // Exit C frame and return. 1529 // Exit C frame and return.
1461 // r0:r1: result 1530 // r3:r4: result
1462 // sp: stack pointer 1531 // sp: stack pointer
1463 // fp: frame pointer 1532 // fp: frame pointer
1464 // Callee-saved register r4 still holds argc. 1533 // r14: still holds argc (callee-saved).
1465 __ LeaveExitFrame(save_doubles_, r4, true); 1534 __ LeaveExitFrame(save_doubles_, r14, true);
1466 __ mov(pc, lr); 1535 __ blr();
1467 1536
1468 // Handling of exception. 1537 // Handling of exception.
1469 __ bind(&exception_returned); 1538 __ bind(&exception_returned);
1470 1539
1471 // Retrieve the pending exception. 1540 // Retrieve the pending exception.
1472 __ mov(r2, Operand(pending_exception_address)); 1541 __ mov(r5, Operand(pending_exception_address));
1473 __ ldr(r0, MemOperand(r2)); 1542 __ LoadP(r3, MemOperand(r5));
1474 1543
1475 // Clear the pending exception. 1544 // Clear the pending exception.
1476 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); 1545 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
1477 __ str(r3, MemOperand(r2)); 1546 __ StoreP(r6, MemOperand(r5));
1478 1547
1479 // Special handling of termination exceptions which are uncatchable 1548 // Special handling of termination exceptions which are uncatchable
1480 // by javascript code. 1549 // by javascript code.
1481 Label throw_termination_exception; 1550 Label throw_termination_exception;
1482 __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex); 1551 __ CompareRoot(r3, Heap::kTerminationExceptionRootIndex);
1483 __ b(eq, &throw_termination_exception); 1552 __ beq(&throw_termination_exception);
1484 1553
1485 // Handle normal exception. 1554 // Handle normal exception.
1486 __ Throw(r0); 1555 __ Throw(r3);
1487 1556
1488 __ bind(&throw_termination_exception); 1557 __ bind(&throw_termination_exception);
1489 __ ThrowUncatchable(r0); 1558 __ ThrowUncatchable(r3);
1490 } 1559 }
1491 1560
1492 1561
1493 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 1562 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
1494 // r0: code entry 1563 // r3: code entry
1495 // r1: function 1564 // r4: function
1496 // r2: receiver 1565 // r5: receiver
1497 // r3: argc 1566 // r6: argc
1498 // [sp+0]: argv 1567 // [sp+0]: argv
1499 1568
1500 Label invoke, handler_entry, exit; 1569 Label invoke, handler_entry, exit;
1501 1570
1571 // Called from C
1572 #if ABI_USES_FUNCTION_DESCRIPTORS
1573 __ function_descriptor();
1574 #endif
1575
1502 ProfileEntryHookStub::MaybeCallEntryHook(masm); 1576 ProfileEntryHookStub::MaybeCallEntryHook(masm);
1503 1577
1504 // Called from C, so do not pop argc and args on exit (preserve sp) 1578 // PPC LINUX ABI:
1505 // No need to save register-passed args 1579 // preserve LR in pre-reserved slot in caller's frame
1506 // Save callee-saved registers (incl. cp and fp), sp, and lr 1580 __ mflr(r0);
1507 __ stm(db_w, sp, kCalleeSaved | lr.bit()); 1581 __ StoreP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
1508 1582
1509 // Save callee-saved vfp registers. 1583 // Save callee saved registers on the stack.
1510 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); 1584 __ MultiPush(kCalleeSaved);
1511 // Set up the reserved register for 0.0.
1512 __ vmov(kDoubleRegZero, 0.0);
1513 __ VFPEnsureFPSCRState(r4);
1514 1585
1515 // Get address of argv, see stm above. 1586 // Floating point regs FPR0 - FRP13 are volatile
1516 // r0: code entry 1587 // FPR14-FPR31 are non-volatile, but sub-calls will save them for us
1517 // r1: function
1518 // r2: receiver
1519 // r3: argc
1520 1588
1521 // Set up argv in r4. 1589 // int offset_to_argv = kPointerSize * 22; // matches (22*4) above
1522 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; 1590 // __ lwz(r7, MemOperand(sp, offset_to_argv));
1523 offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize;
1524 __ ldr(r4, MemOperand(sp, offset_to_argv));
1525 1591
1526 // Push a frame with special values setup to mark it as an entry frame. 1592 // Push a frame with special values setup to mark it as an entry frame.
1527 // r0: code entry 1593 // r3: code entry
1528 // r1: function 1594 // r4: function
1529 // r2: receiver 1595 // r5: receiver
1530 // r3: argc 1596 // r6: argc
1531 // r4: argv 1597 // r7: argv
1598 __ li(r0, Operand(-1)); // Push a bad frame pointer to fail if it is used.
1599 __ push(r0);
1600 #if V8_OOL_CONSTANT_POOL
1601 __ mov(kConstantPoolRegister,
1602 Operand(isolate()->factory()->empty_constant_pool_array()));
1603 __ push(kConstantPoolRegister);
1604 #endif
1532 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 1605 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
1533 if (FLAG_enable_ool_constant_pool) { 1606 __ LoadSmiLiteral(r0, Smi::FromInt(marker));
1534 __ mov(r8, Operand(isolate()->factory()->empty_constant_pool_array())); 1607 __ push(r0);
1535 } 1608 __ push(r0);
1536 __ mov(r7, Operand(Smi::FromInt(marker))); 1609 // Save copies of the top frame descriptor on the stack.
1537 __ mov(r6, Operand(Smi::FromInt(marker))); 1610 __ mov(r8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1538 __ mov(r5, 1611 __ LoadP(r0, MemOperand(r8));
1539 Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1612 __ push(r0);
1540 __ ldr(r5, MemOperand(r5));
1541 __ mov(ip, Operand(-1)); // Push a bad frame pointer to fail if it is used.
1542 __ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() |
1543 (FLAG_enable_ool_constant_pool ? r8.bit() : 0) |
1544 ip.bit());
1545 1613
1546 // Set up frame pointer for the frame to be pushed. 1614 // Set up frame pointer for the frame to be pushed.
1547 __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1615 __ addi(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1548 1616
1549 // If this is the outermost JS call, set js_entry_sp value. 1617 // If this is the outermost JS call, set js_entry_sp value.
1550 Label non_outermost_js; 1618 Label non_outermost_js;
1551 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate()); 1619 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate());
1552 __ mov(r5, Operand(ExternalReference(js_entry_sp))); 1620 __ mov(r8, Operand(ExternalReference(js_entry_sp)));
1553 __ ldr(r6, MemOperand(r5)); 1621 __ LoadP(r9, MemOperand(r8));
1554 __ cmp(r6, Operand::Zero()); 1622 __ cmpi(r9, Operand::Zero());
1555 __ b(ne, &non_outermost_js); 1623 __ bne(&non_outermost_js);
1556 __ str(fp, MemOperand(r5)); 1624 __ StoreP(fp, MemOperand(r8));
1557 __ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 1625 __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
1558 Label cont; 1626 Label cont;
1559 __ b(&cont); 1627 __ b(&cont);
1560 __ bind(&non_outermost_js); 1628 __ bind(&non_outermost_js);
1561 __ mov(ip, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); 1629 __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
1562 __ bind(&cont); 1630 __ bind(&cont);
1563 __ push(ip); 1631 __ push(ip); // frame-type
1564 1632
1565 // Jump to a faked try block that does the invoke, with a faked catch 1633 // Jump to a faked try block that does the invoke, with a faked catch
1566 // block that sets the pending exception. 1634 // block that sets the pending exception.
1567 __ jmp(&invoke); 1635 __ b(&invoke);
1568 1636
1569 // Block literal pool emission whilst taking the position of the handler 1637 __ bind(&handler_entry);
1570 // entry. This avoids making the assumption that literal pools are always 1638 handler_offset_ = handler_entry.pos();
1571 // emitted after an instruction is emitted, rather than before. 1639 // Caught exception: Store result (exception) in the pending exception
1572 { 1640 // field in the JSEnv and return a failure sentinel. Coming in here the
1573 Assembler::BlockConstPoolScope block_const_pool(masm); 1641 // fp will be invalid because the PushTryHandler below sets it to 0 to
1574 __ bind(&handler_entry); 1642 // signal the existence of the JSEntry frame.
1575 handler_offset_ = handler_entry.pos(); 1643 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1576 // Caught exception: Store result (exception) in the pending exception 1644 isolate())));
1577 // field in the JSEnv and return a failure sentinel. Coming in here the 1645
1578 // fp will be invalid because the PushTryHandler below sets it to 0 to 1646 __ StoreP(r3, MemOperand(ip));
1579 // signal the existence of the JSEntry frame. 1647 __ LoadRoot(r3, Heap::kExceptionRootIndex);
1580 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1581 isolate())));
1582 }
1583 __ str(r0, MemOperand(ip));
1584 __ LoadRoot(r0, Heap::kExceptionRootIndex);
1585 __ b(&exit); 1648 __ b(&exit);
1586 1649
1587 // Invoke: Link this frame into the handler chain. There's only one 1650 // Invoke: Link this frame into the handler chain. There's only one
1588 // handler block in this code object, so its index is 0. 1651 // handler block in this code object, so its index is 0.
1589 __ bind(&invoke); 1652 __ bind(&invoke);
1590 // Must preserve r0-r4, r5-r6 are available. 1653 // Must preserve r0-r4, r5-r7 are available. (needs update for PPC)
1591 __ PushTryHandler(StackHandler::JS_ENTRY, 0); 1654 __ PushTryHandler(StackHandler::JS_ENTRY, 0);
1592 // If an exception not caught by another handler occurs, this handler 1655 // If an exception not caught by another handler occurs, this handler
1593 // returns control to the code after the bl(&invoke) above, which 1656 // returns control to the code after the b(&invoke) above, which
1594 // restores all kCalleeSaved registers (including cp and fp) to their 1657 // restores all kCalleeSaved registers (including cp and fp) to their
1595 // saved values before returning a failure to C. 1658 // saved values before returning a failure to C.
1596 1659
1597 // Clear any pending exceptions. 1660 // Clear any pending exceptions.
1598 __ mov(r5, Operand(isolate()->factory()->the_hole_value())); 1661 __ mov(r8, Operand(isolate()->factory()->the_hole_value()));
1599 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1662 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1600 isolate()))); 1663 isolate())));
1601 __ str(r5, MemOperand(ip)); 1664 __ StoreP(r8, MemOperand(ip));
1602 1665
1603 // Invoke the function by calling through JS entry trampoline builtin. 1666 // Invoke the function by calling through JS entry trampoline builtin.
1604 // Notice that we cannot store a reference to the trampoline code directly in 1667 // Notice that we cannot store a reference to the trampoline code directly in
1605 // this stub, because runtime stubs are not traversed when doing GC. 1668 // this stub, because runtime stubs are not traversed when doing GC.
1606 1669
1607 // Expected registers by Builtins::JSEntryTrampoline 1670 // Expected registers by Builtins::JSEntryTrampoline
1608 // r0: code entry 1671 // r3: code entry
1609 // r1: function 1672 // r4: function
1610 // r2: receiver 1673 // r5: receiver
1611 // r3: argc 1674 // r6: argc
1612 // r4: argv 1675 // r7: argv
1613 if (is_construct) { 1676 if (is_construct) {
1614 ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline, 1677 ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
1615 isolate()); 1678 isolate());
1616 __ mov(ip, Operand(construct_entry)); 1679 __ mov(ip, Operand(construct_entry));
1617 } else { 1680 } else {
1618 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate()); 1681 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate());
1619 __ mov(ip, Operand(entry)); 1682 __ mov(ip, Operand(entry));
1620 } 1683 }
1621 __ ldr(ip, MemOperand(ip)); // deref address 1684 __ LoadP(ip, MemOperand(ip)); // deref address
1622 __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
1623 1685
1624 // Branch and link to JSEntryTrampoline. 1686 // Branch and link to JSEntryTrampoline.
1625 __ Call(ip); 1687 // the address points to the start of the code object, skip the header
1688 __ addi(r0, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
1689 __ mtlr(r0);
1690 __ bclr(BA, SetLK); // make the call
1626 1691
1627 // Unlink this frame from the handler chain. 1692 // Unlink this frame from the handler chain.
1628 __ PopTryHandler(); 1693 __ PopTryHandler();
1629 1694
1630 __ bind(&exit); // r0 holds result 1695 __ bind(&exit); // r3 holds result
1631 // Check if the current stack frame is marked as the outermost JS frame. 1696 // Check if the current stack frame is marked as the outermost JS frame.
1632 Label non_outermost_js_2; 1697 Label non_outermost_js_2;
1633 __ pop(r5); 1698 __ pop(r8);
1634 __ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); 1699 __ CmpSmiLiteral(r8, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME), r0);
1635 __ b(ne, &non_outermost_js_2); 1700 __ bne(&non_outermost_js_2);
1636 __ mov(r6, Operand::Zero()); 1701 __ mov(r9, Operand::Zero());
1637 __ mov(r5, Operand(ExternalReference(js_entry_sp))); 1702 __ mov(r8, Operand(ExternalReference(js_entry_sp)));
1638 __ str(r6, MemOperand(r5)); 1703 __ StoreP(r9, MemOperand(r8));
1639 __ bind(&non_outermost_js_2); 1704 __ bind(&non_outermost_js_2);
1640 1705
1641 // Restore the top frame descriptors from the stack. 1706 // Restore the top frame descriptors from the stack.
1642 __ pop(r3); 1707 __ pop(r6);
1643 __ mov(ip, 1708 __ mov(ip,
1644 Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); 1709 Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate())));
1645 __ str(r3, MemOperand(ip)); 1710 __ StoreP(r6, MemOperand(ip));
1646 1711
1647 // Reset the stack to the callee saved registers. 1712 // Reset the stack to the callee saved registers.
1648 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); 1713 __ addi(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1649 1714
1650 // Restore callee-saved registers and return. 1715 // Restore callee-saved registers and return.
1651 #ifdef DEBUG 1716 #ifdef DEBUG
1652 if (FLAG_debug_code) { 1717 if (FLAG_debug_code) {
1653 __ mov(lr, Operand(pc)); 1718 Label here;
1719 __ b(&here, SetLK);
1720 __ bind(&here);
1654 } 1721 }
1655 #endif 1722 #endif
1656 1723
1657 // Restore callee-saved vfp registers. 1724 __ MultiPop(kCalleeSaved);
1658 __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
1659 1725
1660 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); 1726 __ LoadP(r0, MemOperand(sp, kStackFrameLRSlot * kPointerSize));
1727 __ mtctr(r0);
1728 __ bctr();
1661 } 1729 }
1662 1730
1663 1731
1664 // Uses registers r0 to r4. 1732 // Uses registers r3 to r7.
1665 // Expected input (depending on whether args are in registers or on the stack): 1733 // Expected input (depending on whether args are in registers or on the stack):
1666 // * object: r0 or at sp + 1 * kPointerSize. 1734 // * object: r3 or at sp + 1 * kPointerSize.
1667 // * function: r1 or at sp. 1735 // * function: r4 or at sp.
1668 // 1736 //
1669 // An inlined call site may have been generated before calling this stub. 1737 // An inlined call site may have been generated before calling this stub.
1670 // In this case the offset to the inline sites to patch are passed in r5 and r6. 1738 // In this case the offset to the inline site to patch is passed in r8.
1671 // (See LCodeGen::DoInstanceOfKnownGlobal) 1739 // (See LCodeGen::DoInstanceOfKnownGlobal)
1672 void InstanceofStub::Generate(MacroAssembler* masm) { 1740 void InstanceofStub::Generate(MacroAssembler* masm) {
1673 // Call site inlining and patching implies arguments in registers. 1741 // Call site inlining and patching implies arguments in registers.
1674 ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck()); 1742 ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck());
1675 // ReturnTrueFalse is only implemented for inlined call sites. 1743 // ReturnTrueFalse is only implemented for inlined call sites.
1676 ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); 1744 ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck());
1677 1745
1678 // Fixed register usage throughout the stub: 1746 // Fixed register usage throughout the stub:
1679 const Register object = r0; // Object (lhs). 1747 const Register object = r3; // Object (lhs).
1680 Register map = r3; // Map of the object. 1748 Register map = r6; // Map of the object.
1681 const Register function = r1; // Function (rhs). 1749 const Register function = r4; // Function (rhs).
1682 const Register prototype = r4; // Prototype of the function. 1750 const Register prototype = r7; // Prototype of the function.
1683 const Register scratch = r2; 1751 const Register inline_site = r9;
1752 const Register scratch = r5;
1753 Register scratch3 = no_reg;
1754
1755 // delta = mov + unaligned LoadP + cmp + bne
1756 #if V8_TARGET_ARCH_PPC64
1757 const int32_t kDeltaToLoadBoolResult =
1758 (Assembler::kMovInstructions + 4) * Assembler::kInstrSize;
1759 #else
1760 const int32_t kDeltaToLoadBoolResult =
1761 (Assembler::kMovInstructions + 3) * Assembler::kInstrSize;
1762 #endif
1684 1763
1685 Label slow, loop, is_instance, is_not_instance, not_js_object; 1764 Label slow, loop, is_instance, is_not_instance, not_js_object;
1686 1765
1687 if (!HasArgsInRegisters()) { 1766 if (!HasArgsInRegisters()) {
1688 __ ldr(object, MemOperand(sp, 1 * kPointerSize)); 1767 __ LoadP(object, MemOperand(sp, 1 * kPointerSize));
1689 __ ldr(function, MemOperand(sp, 0)); 1768 __ LoadP(function, MemOperand(sp, 0));
1690 } 1769 }
1691 1770
1692 // Check that the left hand is a JS object and load map. 1771 // Check that the left hand is a JS object and load map.
1693 __ JumpIfSmi(object, &not_js_object); 1772 __ JumpIfSmi(object, &not_js_object);
1694 __ IsObjectJSObjectType(object, map, scratch, &not_js_object); 1773 __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
1695 1774
1696 // If there is a call site cache don't look in the global cache, but do the 1775 // If there is a call site cache don't look in the global cache, but do the
1697 // real lookup and update the call site cache. 1776 // real lookup and update the call site cache.
1698 if (!HasCallSiteInlineCheck()) { 1777 if (!HasCallSiteInlineCheck()) {
1699 Label miss; 1778 Label miss;
1700 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 1779 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
1701 __ b(ne, &miss); 1780 __ bne(&miss);
1702 __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex); 1781 __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex);
1703 __ b(ne, &miss); 1782 __ bne(&miss);
1704 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 1783 __ LoadRoot(r3, Heap::kInstanceofCacheAnswerRootIndex);
1705 __ Ret(HasArgsInRegisters() ? 0 : 2); 1784 __ Ret(HasArgsInRegisters() ? 0 : 2);
1706 1785
1707 __ bind(&miss); 1786 __ bind(&miss);
1708 } 1787 }
1709 1788
1710 // Get the prototype of the function. 1789 // Get the prototype of the function.
1711 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); 1790 __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true);
1712 1791
1713 // Check that the function prototype is a JS object. 1792 // Check that the function prototype is a JS object.
1714 __ JumpIfSmi(prototype, &slow); 1793 __ JumpIfSmi(prototype, &slow);
1715 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 1794 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
1716 1795
1717 // Update the global instanceof or call site inlined cache with the current 1796 // Update the global instanceof or call site inlined cache with the current
1718 // map and function. The cached answer will be set when it is known below. 1797 // map and function. The cached answer will be set when it is known below.
1719 if (!HasCallSiteInlineCheck()) { 1798 if (!HasCallSiteInlineCheck()) {
1720 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); 1799 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
1721 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); 1800 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
1722 } else { 1801 } else {
1723 ASSERT(HasArgsInRegisters()); 1802 ASSERT(HasArgsInRegisters());
1724 // Patch the (relocated) inlined map check. 1803 // Patch the (relocated) inlined map check.
1725 1804
1726 // The map_load_offset was stored in r5 1805 // The offset was stored in r8
1727 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal). 1806 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
1728 const Register map_load_offset = r5; 1807 const Register offset = r8;
1729 __ sub(r9, lr, map_load_offset); 1808 __ mflr(inline_site);
1730 // Get the map location in r5 and patch it. 1809 __ sub(inline_site, inline_site, offset);
1731 __ GetRelocatedValueLocation(r9, map_load_offset, scratch); 1810 // Get the map location in r8 and patch it.
1732 __ ldr(map_load_offset, MemOperand(map_load_offset)); 1811 __ GetRelocatedValue(inline_site, offset, scratch);
1733 __ str(map, FieldMemOperand(map_load_offset, Cell::kValueOffset)); 1812 __ StoreP(map, FieldMemOperand(offset, Cell::kValueOffset), r0);
1734 } 1813 }
1735 1814
1736 // Register mapping: r3 is object map and r4 is function prototype. 1815 // Register mapping: r6 is object map and r7 is function prototype.
1737 // Get prototype of object into r2. 1816 // Get prototype of object into r5.
1738 __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset)); 1817 __ LoadP(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
1739 1818
1740 // We don't need map any more. Use it as a scratch register. 1819 // We don't need map any more. Use it as a scratch register.
1741 Register scratch2 = map; 1820 scratch3 = map;
1742 map = no_reg; 1821 map = no_reg;
1743 1822
1744 // Loop through the prototype chain looking for the function prototype. 1823 // Loop through the prototype chain looking for the function prototype.
1745 __ LoadRoot(scratch2, Heap::kNullValueRootIndex); 1824 __ LoadRoot(scratch3, Heap::kNullValueRootIndex);
1746 __ bind(&loop); 1825 __ bind(&loop);
1747 __ cmp(scratch, Operand(prototype)); 1826 __ cmp(scratch, prototype);
1748 __ b(eq, &is_instance); 1827 __ beq(&is_instance);
1749 __ cmp(scratch, scratch2); 1828 __ cmp(scratch, scratch3);
1750 __ b(eq, &is_not_instance); 1829 __ beq(&is_not_instance);
1751 __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); 1830 __ LoadP(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
1752 __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); 1831 __ LoadP(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
1753 __ jmp(&loop); 1832 __ b(&loop);
1754 1833
1755 __ bind(&is_instance); 1834 __ bind(&is_instance);
1756 if (!HasCallSiteInlineCheck()) { 1835 if (!HasCallSiteInlineCheck()) {
1757 __ mov(r0, Operand(Smi::FromInt(0))); 1836 __ LoadSmiLiteral(r3, Smi::FromInt(0));
1758 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 1837 __ StoreRoot(r3, Heap::kInstanceofCacheAnswerRootIndex);
1759 } else { 1838 } else {
1760 // Patch the call site to return true. 1839 // Patch the call site to return true.
1761 __ LoadRoot(r0, Heap::kTrueValueRootIndex); 1840 __ LoadRoot(r3, Heap::kTrueValueRootIndex);
1762 // The bool_load_offset was stored in r6 1841 __ addi(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
1763 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
1764 const Register bool_load_offset = r6;
1765 __ sub(r9, lr, bool_load_offset);
1766 // Get the boolean result location in scratch and patch it. 1842 // Get the boolean result location in scratch and patch it.
1767 __ GetRelocatedValueLocation(r9, scratch, scratch2); 1843 __ SetRelocatedValue(inline_site, scratch, r3);
1768 __ str(r0, MemOperand(scratch));
1769 1844
1770 if (!ReturnTrueFalseObject()) { 1845 if (!ReturnTrueFalseObject()) {
1771 __ mov(r0, Operand(Smi::FromInt(0))); 1846 __ LoadSmiLiteral(r3, Smi::FromInt(0));
1772 } 1847 }
1773 } 1848 }
1774 __ Ret(HasArgsInRegisters() ? 0 : 2); 1849 __ Ret(HasArgsInRegisters() ? 0 : 2);
1775 1850
1776 __ bind(&is_not_instance); 1851 __ bind(&is_not_instance);
1777 if (!HasCallSiteInlineCheck()) { 1852 if (!HasCallSiteInlineCheck()) {
1778 __ mov(r0, Operand(Smi::FromInt(1))); 1853 __ LoadSmiLiteral(r3, Smi::FromInt(1));
1779 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); 1854 __ StoreRoot(r3, Heap::kInstanceofCacheAnswerRootIndex);
1780 } else { 1855 } else {
1781 // Patch the call site to return false. 1856 // Patch the call site to return false.
1782 __ LoadRoot(r0, Heap::kFalseValueRootIndex); 1857 __ LoadRoot(r3, Heap::kFalseValueRootIndex);
1783 // The bool_load_offset was stored in r6 1858 __ addi(inline_site, inline_site, Operand(kDeltaToLoadBoolResult));
1784 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal).
1785 const Register bool_load_offset = r6;
1786 __ sub(r9, lr, bool_load_offset);
1787 ;
1788 // Get the boolean result location in scratch and patch it. 1859 // Get the boolean result location in scratch and patch it.
1789 __ GetRelocatedValueLocation(r9, scratch, scratch2); 1860 __ SetRelocatedValue(inline_site, scratch, r3);
1790 __ str(r0, MemOperand(scratch));
1791 1861
1792 if (!ReturnTrueFalseObject()) { 1862 if (!ReturnTrueFalseObject()) {
1793 __ mov(r0, Operand(Smi::FromInt(1))); 1863 __ LoadSmiLiteral(r3, Smi::FromInt(1));
1794 } 1864 }
1795 } 1865 }
1796 __ Ret(HasArgsInRegisters() ? 0 : 2); 1866 __ Ret(HasArgsInRegisters() ? 0 : 2);
1797 1867
1798 Label object_not_null, object_not_null_or_smi; 1868 Label object_not_null, object_not_null_or_smi;
1799 __ bind(&not_js_object); 1869 __ bind(&not_js_object);
1800 // Before null, smi and string value checks, check that the rhs is a function 1870 // Before null, smi and string value checks, check that the rhs is a function
1801 // as for a non-function rhs an exception needs to be thrown. 1871 // as for a non-function rhs an exception needs to be thrown.
1802 __ JumpIfSmi(function, &slow); 1872 __ JumpIfSmi(function, &slow);
1803 __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE); 1873 __ CompareObjectType(function, scratch3, scratch, JS_FUNCTION_TYPE);
1804 __ b(ne, &slow); 1874 __ bne(&slow);
1805 1875
1806 // Null is not instance of anything. 1876 // Null is not instance of anything.
1807 __ cmp(scratch, Operand(isolate()->factory()->null_value())); 1877 __ Cmpi(scratch, Operand(isolate()->factory()->null_value()), r0);
1808 __ b(ne, &object_not_null); 1878 __ bne(&object_not_null);
1809 __ mov(r0, Operand(Smi::FromInt(1))); 1879 __ LoadSmiLiteral(r3, Smi::FromInt(1));
1810 __ Ret(HasArgsInRegisters() ? 0 : 2); 1880 __ Ret(HasArgsInRegisters() ? 0 : 2);
1811 1881
1812 __ bind(&object_not_null); 1882 __ bind(&object_not_null);
1813 // Smi values are not instances of anything. 1883 // Smi values are not instances of anything.
1814 __ JumpIfNotSmi(object, &object_not_null_or_smi); 1884 __ JumpIfNotSmi(object, &object_not_null_or_smi);
1815 __ mov(r0, Operand(Smi::FromInt(1))); 1885 __ LoadSmiLiteral(r3, Smi::FromInt(1));
1816 __ Ret(HasArgsInRegisters() ? 0 : 2); 1886 __ Ret(HasArgsInRegisters() ? 0 : 2);
1817 1887
1818 __ bind(&object_not_null_or_smi); 1888 __ bind(&object_not_null_or_smi);
1819 // String values are not instances of anything. 1889 // String values are not instances of anything.
1820 __ IsObjectJSStringType(object, scratch, &slow); 1890 __ IsObjectJSStringType(object, scratch, &slow);
1821 __ mov(r0, Operand(Smi::FromInt(1))); 1891 __ LoadSmiLiteral(r3, Smi::FromInt(1));
1822 __ Ret(HasArgsInRegisters() ? 0 : 2); 1892 __ Ret(HasArgsInRegisters() ? 0 : 2);
1823 1893
1824 // Slow-case. Tail call builtin. 1894 // Slow-case. Tail call builtin.
1825 __ bind(&slow); 1895 __ bind(&slow);
1826 if (!ReturnTrueFalseObject()) { 1896 if (!ReturnTrueFalseObject()) {
1827 if (HasArgsInRegisters()) { 1897 if (HasArgsInRegisters()) {
1828 __ Push(r0, r1); 1898 __ Push(r3, r4);
1829 } 1899 }
1830 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 1900 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
1831 } else { 1901 } else {
1832 { 1902 {
1833 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 1903 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
1834 __ Push(r0, r1); 1904 __ Push(r3, r4);
1835 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); 1905 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
1836 } 1906 }
1837 __ cmp(r0, Operand::Zero()); 1907 Label true_value, done;
1838 __ LoadRoot(r0, Heap::kTrueValueRootIndex, eq); 1908 __ cmpi(r3, Operand::Zero());
1839 __ LoadRoot(r0, Heap::kFalseValueRootIndex, ne); 1909 __ beq(&true_value);
1910
1911 __ LoadRoot(r3, Heap::kFalseValueRootIndex);
1912 __ b(&done);
1913
1914 __ bind(&true_value);
1915 __ LoadRoot(r3, Heap::kTrueValueRootIndex);
1916
1917 __ bind(&done);
1840 __ Ret(HasArgsInRegisters() ? 0 : 2); 1918 __ Ret(HasArgsInRegisters() ? 0 : 2);
1841 } 1919 }
1842 } 1920 }
1843 1921
1844 1922
1845 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { 1923 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
1846 Label miss; 1924 Label miss;
1847 Register receiver = LoadIC::ReceiverRegister(); 1925 Register receiver = LoadIC::ReceiverRegister();
1848 1926
1849 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, 1927 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r6,
1850 r4, &miss); 1928 r7, &miss);
1851 __ bind(&miss); 1929 __ bind(&miss);
1852 PropertyAccessCompiler::TailCallBuiltin( 1930 PropertyAccessCompiler::TailCallBuiltin(
1853 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); 1931 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
1854 } 1932 }
1855 1933
1856 1934
1857 Register InstanceofStub::left() { return r0; } 1935 Register InstanceofStub::left() { return r3; }
1858 1936
1859 1937
1860 Register InstanceofStub::right() { return r1; } 1938 Register InstanceofStub::right() { return r4; }
1861 1939
1862 1940
1863 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 1941 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
1864 // The displacement is the offset of the last parameter (if any) 1942 // The displacement is the offset of the last parameter (if any)
1865 // relative to the frame pointer. 1943 // relative to the frame pointer.
1866 const int kDisplacement = 1944 const int kDisplacement =
1867 StandardFrameConstants::kCallerSPOffset - kPointerSize; 1945 StandardFrameConstants::kCallerSPOffset - kPointerSize;
1868 1946
1869 // Check that the key is a smi. 1947 // Check that the key is a smi.
1870 Label slow; 1948 Label slow;
1871 __ JumpIfNotSmi(r1, &slow); 1949 __ JumpIfNotSmi(r4, &slow);
1872 1950
1873 // Check if the calling frame is an arguments adaptor frame. 1951 // Check if the calling frame is an arguments adaptor frame.
1874 Label adaptor; 1952 Label adaptor;
1875 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 1953 __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1876 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 1954 __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kContextOffset));
1877 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 1955 STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
1878 __ b(eq, &adaptor); 1956 __ CmpSmiLiteral(r6, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
1957 __ beq(&adaptor);
1879 1958
1880 // Check index against formal parameters count limit passed in 1959 // Check index against formal parameters count limit passed in
1881 // through register r0. Use unsigned comparison to get negative 1960 // through register r3. Use unsigned comparison to get negative
1882 // check for free. 1961 // check for free.
1883 __ cmp(r1, r0); 1962 __ cmpl(r4, r3);
1884 __ b(hs, &slow); 1963 __ bge(&slow);
1885 1964
1886 // Read the argument from the stack and return it. 1965 // Read the argument from the stack and return it.
1887 __ sub(r3, r0, r1); 1966 __ sub(r6, r3, r4);
1888 __ add(r3, fp, Operand::PointerOffsetFromSmiKey(r3)); 1967 __ SmiToPtrArrayOffset(r6, r6);
1889 __ ldr(r0, MemOperand(r3, kDisplacement)); 1968 __ add(r6, fp, r6);
1890 __ Jump(lr); 1969 __ LoadP(r3, MemOperand(r6, kDisplacement));
1970 __ blr();
1891 1971
1892 // Arguments adaptor case: Check index against actual arguments 1972 // Arguments adaptor case: Check index against actual arguments
1893 // limit found in the arguments adaptor frame. Use unsigned 1973 // limit found in the arguments adaptor frame. Use unsigned
1894 // comparison to get negative check for free. 1974 // comparison to get negative check for free.
1895 __ bind(&adaptor); 1975 __ bind(&adaptor);
1896 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 1976 __ LoadP(r3, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
1897 __ cmp(r1, r0); 1977 __ cmpl(r4, r3);
1898 __ b(cs, &slow); 1978 __ bge(&slow);
1899 1979
1900 // Read the argument from the adaptor frame and return it. 1980 // Read the argument from the adaptor frame and return it.
1901 __ sub(r3, r0, r1); 1981 __ sub(r6, r3, r4);
1902 __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r3)); 1982 __ SmiToPtrArrayOffset(r6, r6);
1903 __ ldr(r0, MemOperand(r3, kDisplacement)); 1983 __ add(r6, r5, r6);
1904 __ Jump(lr); 1984 __ LoadP(r3, MemOperand(r6, kDisplacement));
1985 __ blr();
1905 1986
1906 // Slow-case: Handle non-smi or out-of-bounds access to arguments 1987 // Slow-case: Handle non-smi or out-of-bounds access to arguments
1907 // by calling the runtime system. 1988 // by calling the runtime system.
1908 __ bind(&slow); 1989 __ bind(&slow);
1909 __ push(r1); 1990 __ push(r4);
1910 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 1991 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
1911 } 1992 }
1912 1993
1913 1994
1914 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { 1995 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
1915 // sp[0] : number of parameters 1996 // sp[0] : number of parameters
1916 // sp[4] : receiver displacement 1997 // sp[1] : receiver displacement
1917 // sp[8] : function 1998 // sp[2] : function
1918 1999
1919 // Check if the calling frame is an arguments adaptor frame. 2000 // Check if the calling frame is an arguments adaptor frame.
1920 Label runtime; 2001 Label runtime;
1921 __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2002 __ LoadP(r6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1922 __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset)); 2003 __ LoadP(r5, MemOperand(r6, StandardFrameConstants::kContextOffset));
1923 __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2004 STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
1924 __ b(ne, &runtime); 2005 __ CmpSmiLiteral(r5, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
2006 __ bne(&runtime);
1925 2007
1926 // Patch the arguments.length and the parameters pointer in the current frame. 2008 // Patch the arguments.length and the parameters pointer in the current frame.
1927 __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2009 __ LoadP(r5, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset));
1928 __ str(r2, MemOperand(sp, 0 * kPointerSize)); 2010 __ StoreP(r5, MemOperand(sp, 0 * kPointerSize));
1929 __ add(r3, r3, Operand(r2, LSL, 1)); 2011 __ SmiToPtrArrayOffset(r5, r5);
1930 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); 2012 __ add(r6, r6, r5);
1931 __ str(r3, MemOperand(sp, 1 * kPointerSize)); 2013 __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
2014 __ StoreP(r6, MemOperand(sp, 1 * kPointerSize));
1932 2015
1933 __ bind(&runtime); 2016 __ bind(&runtime);
1934 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 2017 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
1935 } 2018 }
1936 2019
1937 2020
1938 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { 2021 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
1939 // Stack layout: 2022 // Stack layout:
1940 // sp[0] : number of parameters (tagged) 2023 // sp[0] : number of parameters (tagged)
1941 // sp[4] : address of receiver argument 2024 // sp[1] : address of receiver argument
1942 // sp[8] : function 2025 // sp[2] : function
1943 // Registers used over whole function: 2026 // Registers used over whole function:
1944 // r6 : allocated object (tagged) 2027 // r9 : allocated object (tagged)
1945 // r9 : mapped parameter count (tagged) 2028 // r11 : mapped parameter count (tagged)
1946 2029
1947 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); 2030 __ LoadP(r4, MemOperand(sp, 0 * kPointerSize));
1948 // r1 = parameter count (tagged) 2031 // r4 = parameter count (tagged)
1949 2032
1950 // Check if the calling frame is an arguments adaptor frame. 2033 // Check if the calling frame is an arguments adaptor frame.
1951 Label runtime; 2034 Label runtime;
1952 Label adaptor_frame, try_allocate; 2035 Label adaptor_frame, try_allocate;
1953 __ ldr(r3, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2036 __ LoadP(r6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1954 __ ldr(r2, MemOperand(r3, StandardFrameConstants::kContextOffset)); 2037 __ LoadP(r5, MemOperand(r6, StandardFrameConstants::kContextOffset));
1955 __ cmp(r2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2038 STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
1956 __ b(eq, &adaptor_frame); 2039 __ CmpSmiLiteral(r5, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
2040 __ beq(&adaptor_frame);
1957 2041
1958 // No adaptor, parameter count = argument count. 2042 // No adaptor, parameter count = argument count.
1959 __ mov(r2, r1); 2043 __ mr(r5, r4);
1960 __ b(&try_allocate); 2044 __ b(&try_allocate);
1961 2045
1962 // We have an adaptor frame. Patch the parameters pointer. 2046 // We have an adaptor frame. Patch the parameters pointer.
1963 __ bind(&adaptor_frame); 2047 __ bind(&adaptor_frame);
1964 __ ldr(r2, MemOperand(r3, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2048 __ LoadP(r5, MemOperand(r6, ArgumentsAdaptorFrameConstants::kLengthOffset));
1965 __ add(r3, r3, Operand(r2, LSL, 1)); 2049 __ SmiToPtrArrayOffset(r7, r5);
1966 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); 2050 __ add(r6, r6, r7);
1967 __ str(r3, MemOperand(sp, 1 * kPointerSize)); 2051 __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
2052 __ StoreP(r6, MemOperand(sp, 1 * kPointerSize));
1968 2053
1969 // r1 = parameter count (tagged) 2054 // r4 = parameter count (tagged)
1970 // r2 = argument count (tagged) 2055 // r5 = argument count (tagged)
1971 // Compute the mapped parameter count = min(r1, r2) in r1. 2056 // Compute the mapped parameter count = min(r4, r5) in r4.
1972 __ cmp(r1, Operand(r2)); 2057 Label skip;
1973 __ mov(r1, Operand(r2), LeaveCC, gt); 2058 __ cmp(r4, r5);
2059 __ blt(&skip);
2060 __ mr(r4, r5);
2061 __ bind(&skip);
1974 2062
1975 __ bind(&try_allocate); 2063 __ bind(&try_allocate);
1976 2064
1977 // Compute the sizes of backing store, parameter map, and arguments object. 2065 // Compute the sizes of backing store, parameter map, and arguments object.
1978 // 1. Parameter map, has 2 extra words containing context and backing store. 2066 // 1. Parameter map, has 2 extra words containing context and backing store.
1979 const int kParameterMapHeaderSize = 2067 const int kParameterMapHeaderSize =
1980 FixedArray::kHeaderSize + 2 * kPointerSize; 2068 FixedArray::kHeaderSize + 2 * kPointerSize;
1981 // If there are no mapped parameters, we do not need the parameter_map. 2069 // If there are no mapped parameters, we do not need the parameter_map.
1982 __ cmp(r1, Operand(Smi::FromInt(0))); 2070 Label skip2, skip3;
1983 __ mov(r9, Operand::Zero(), LeaveCC, eq); 2071 __ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
1984 __ mov(r9, Operand(r1, LSL, 1), LeaveCC, ne); 2072 __ bne(&skip2);
1985 __ add(r9, r9, Operand(kParameterMapHeaderSize), LeaveCC, ne); 2073 __ li(r11, Operand::Zero());
2074 __ b(&skip3);
2075 __ bind(&skip2);
2076 __ SmiToPtrArrayOffset(r11, r4);
2077 __ addi(r11, r11, Operand(kParameterMapHeaderSize));
2078 __ bind(&skip3);
1986 2079
1987 // 2. Backing store. 2080 // 2. Backing store.
1988 __ add(r9, r9, Operand(r2, LSL, 1)); 2081 __ SmiToPtrArrayOffset(r7, r5);
1989 __ add(r9, r9, Operand(FixedArray::kHeaderSize)); 2082 __ add(r11, r11, r7);
2083 __ addi(r11, r11, Operand(FixedArray::kHeaderSize));
1990 2084
1991 // 3. Arguments object. 2085 // 3. Arguments object.
1992 __ add(r9, r9, Operand(Heap::kSloppyArgumentsObjectSize)); 2086 __ addi(r11, r11, Operand(Heap::kSloppyArgumentsObjectSize));
1993 2087
1994 // Do the allocation of all three objects in one go. 2088 // Do the allocation of all three objects in one go.
1995 __ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT); 2089 __ Allocate(r11, r3, r6, r7, &runtime, TAG_OBJECT);
1996 2090
1997 // r0 = address of new object(s) (tagged) 2091 // r3 = address of new object(s) (tagged)
1998 // r2 = argument count (smi-tagged) 2092 // r5 = argument count (smi-tagged)
1999 // Get the arguments boilerplate from the current native context into r4. 2093 // Get the arguments boilerplate from the current native context into r4.
2000 const int kNormalOffset = 2094 const int kNormalOffset =
2001 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); 2095 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX);
2002 const int kAliasedOffset = 2096 const int kAliasedOffset =
2003 Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX); 2097 Context::SlotOffset(Context::ALIASED_ARGUMENTS_MAP_INDEX);
2004 2098
2005 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 2099 __ LoadP(r7, MemOperand(cp,
2006 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); 2100 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2007 __ cmp(r1, Operand::Zero()); 2101 __ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset));
2008 __ ldr(r4, MemOperand(r4, kNormalOffset), eq); 2102 Label skip4, skip5;
2009 __ ldr(r4, MemOperand(r4, kAliasedOffset), ne); 2103 __ cmpi(r4, Operand::Zero());
2104 __ bne(&skip4);
2105 __ LoadP(r7, MemOperand(r7, kNormalOffset));
2106 __ b(&skip5);
2107 __ bind(&skip4);
2108 __ LoadP(r7, MemOperand(r7, kAliasedOffset));
2109 __ bind(&skip5);
2010 2110
2011 // r0 = address of new object (tagged) 2111 // r3 = address of new object (tagged)
2012 // r1 = mapped parameter count (tagged) 2112 // r4 = mapped parameter count (tagged)
2013 // r2 = argument count (smi-tagged) 2113 // r5 = argument count (smi-tagged)
2014 // r4 = address of arguments map (tagged) 2114 // r7 = address of arguments map (tagged)
2015 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); 2115 __ StoreP(r7, FieldMemOperand(r3, JSObject::kMapOffset), r0);
2016 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); 2116 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
2017 __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2117 __ StoreP(r6, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0);
2018 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); 2118 __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
2019 2119
2020 // Set up the callee in-object property. 2120 // Set up the callee in-object property.
2021 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); 2121 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
2022 __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); 2122 __ LoadP(r6, MemOperand(sp, 2 * kPointerSize));
2023 __ AssertNotSmi(r3); 2123 __ AssertNotSmi(r6);
2024 const int kCalleeOffset = JSObject::kHeaderSize + 2124 const int kCalleeOffset = JSObject::kHeaderSize +
2025 Heap::kArgumentsCalleeIndex * kPointerSize; 2125 Heap::kArgumentsCalleeIndex * kPointerSize;
2026 __ str(r3, FieldMemOperand(r0, kCalleeOffset)); 2126 __ StoreP(r6, FieldMemOperand(r3, kCalleeOffset), r0);
2027 2127
2028 // Use the length (smi tagged) and set that as an in-object property too. 2128 // Use the length (smi tagged) and set that as an in-object property too.
2029 __ AssertSmi(r2); 2129 __ AssertSmi(r5);
2030 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 2130 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2031 const int kLengthOffset = JSObject::kHeaderSize + 2131 const int kLengthOffset = JSObject::kHeaderSize +
2032 Heap::kArgumentsLengthIndex * kPointerSize; 2132 Heap::kArgumentsLengthIndex * kPointerSize;
2033 __ str(r2, FieldMemOperand(r0, kLengthOffset)); 2133 __ StoreP(r5, FieldMemOperand(r3, kLengthOffset), r0);
2034 2134
2035 // Set up the elements pointer in the allocated arguments object. 2135 // Set up the elements pointer in the allocated arguments object.
2036 // If we allocated a parameter map, r4 will point there, otherwise 2136 // If we allocated a parameter map, r7 will point there, otherwise
2037 // it will point to the backing store. 2137 // it will point to the backing store.
2038 __ add(r4, r0, Operand(Heap::kSloppyArgumentsObjectSize)); 2138 __ addi(r7, r3, Operand(Heap::kSloppyArgumentsObjectSize));
2039 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 2139 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
2040 2140
2041 // r0 = address of new object (tagged) 2141 // r3 = address of new object (tagged)
2042 // r1 = mapped parameter count (tagged) 2142 // r4 = mapped parameter count (tagged)
2043 // r2 = argument count (tagged) 2143 // r5 = argument count (tagged)
2044 // r4 = address of parameter map or backing store (tagged) 2144 // r7 = address of parameter map or backing store (tagged)
2045 // Initialize parameter map. If there are no mapped arguments, we're done. 2145 // Initialize parameter map. If there are no mapped arguments, we're done.
2046 Label skip_parameter_map; 2146 Label skip_parameter_map, skip6;
2047 __ cmp(r1, Operand(Smi::FromInt(0))); 2147 __ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
2048 // Move backing store address to r3, because it is 2148 __ bne(&skip6);
2149 // Move backing store address to r6, because it is
2049 // expected there when filling in the unmapped arguments. 2150 // expected there when filling in the unmapped arguments.
2050 __ mov(r3, r4, LeaveCC, eq); 2151 __ mr(r6, r7);
2051 __ b(eq, &skip_parameter_map); 2152 __ b(&skip_parameter_map);
2153 __ bind(&skip6);
2052 2154
2053 __ LoadRoot(r6, Heap::kSloppyArgumentsElementsMapRootIndex); 2155 __ LoadRoot(r9, Heap::kSloppyArgumentsElementsMapRootIndex);
2054 __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset)); 2156 __ StoreP(r9, FieldMemOperand(r7, FixedArray::kMapOffset), r0);
2055 __ add(r6, r1, Operand(Smi::FromInt(2))); 2157 __ AddSmiLiteral(r9, r4, Smi::FromInt(2), r0);
2056 __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset)); 2158 __ StoreP(r9, FieldMemOperand(r7, FixedArray::kLengthOffset), r0);
2057 __ str(cp, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize)); 2159 __ StoreP(cp, FieldMemOperand(r7,
2058 __ add(r6, r4, Operand(r1, LSL, 1)); 2160 FixedArray::kHeaderSize + 0 * kPointerSize),
2059 __ add(r6, r6, Operand(kParameterMapHeaderSize)); 2161 r0);
2060 __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize)); 2162 __ SmiToPtrArrayOffset(r9, r4);
2163 __ add(r9, r7, r9);
2164 __ addi(r9, r9, Operand(kParameterMapHeaderSize));
2165 __ StoreP(r9, FieldMemOperand(r7,
2166 FixedArray::kHeaderSize + 1 * kPointerSize),
2167 r0);
2061 2168
2062 // Copy the parameter slots and the holes in the arguments. 2169 // Copy the parameter slots and the holes in the arguments.
2063 // We need to fill in mapped_parameter_count slots. They index the context, 2170 // We need to fill in mapped_parameter_count slots. They index the context,
2064 // where parameters are stored in reverse order, at 2171 // where parameters are stored in reverse order, at
2065 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 2172 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
2066 // The mapped parameter thus need to get indices 2173 // The mapped parameter thus need to get indices
2067 // MIN_CONTEXT_SLOTS+parameter_count-1 .. 2174 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
2068 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count 2175 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
2069 // We loop from right to left. 2176 // We loop from right to left.
2070 Label parameters_loop, parameters_test; 2177 Label parameters_loop, parameters_test;
2071 __ mov(r6, r1); 2178 __ mr(r9, r4);
2072 __ ldr(r9, MemOperand(sp, 0 * kPointerSize)); 2179 __ LoadP(r11, MemOperand(sp, 0 * kPointerSize));
2073 __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); 2180 __ AddSmiLiteral(r11, r11, Smi::FromInt(Context::MIN_CONTEXT_SLOTS), r0);
2074 __ sub(r9, r9, Operand(r1)); 2181 __ sub(r11, r11, r4);
2075 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); 2182 __ LoadRoot(r10, Heap::kTheHoleValueRootIndex);
2076 __ add(r3, r4, Operand(r6, LSL, 1)); 2183 __ SmiToPtrArrayOffset(r6, r9);
2077 __ add(r3, r3, Operand(kParameterMapHeaderSize)); 2184 __ add(r6, r7, r6);
2185 __ addi(r6, r6, Operand(kParameterMapHeaderSize));
2078 2186
2079 // r6 = loop variable (tagged) 2187 // r9 = loop variable (tagged)
2080 // r1 = mapping index (tagged) 2188 // r4 = mapping index (tagged)
2081 // r3 = address of backing store (tagged) 2189 // r6 = address of backing store (tagged)
2082 // r4 = address of parameter map (tagged), which is also the address of new 2190 // r7 = address of parameter map (tagged)
2083 // object + Heap::kSloppyArgumentsObjectSize (tagged) 2191 // r8 = temporary scratch (a.o., for address calculation)
2084 // r0 = temporary scratch (a.o., for address calculation) 2192 // r10 = the hole value
2085 // r5 = the hole value 2193 __ b(&parameters_test);
2086 __ jmp(&parameters_test);
2087 2194
2088 __ bind(&parameters_loop); 2195 __ bind(&parameters_loop);
2089 __ sub(r6, r6, Operand(Smi::FromInt(1))); 2196 __ SubSmiLiteral(r9, r9, Smi::FromInt(1), r0);
2090 __ mov(r0, Operand(r6, LSL, 1)); 2197 __ SmiToPtrArrayOffset(r8, r9);
2091 __ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag)); 2198 __ addi(r8, r8, Operand(kParameterMapHeaderSize - kHeapObjectTag));
2092 __ str(r9, MemOperand(r4, r0)); 2199 __ StorePX(r11, MemOperand(r8, r7));
2093 __ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); 2200 __ subi(r8, r8, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
2094 __ str(r5, MemOperand(r3, r0)); 2201 __ StorePX(r10, MemOperand(r8, r6));
2095 __ add(r9, r9, Operand(Smi::FromInt(1))); 2202 __ AddSmiLiteral(r11, r11, Smi::FromInt(1), r0);
2096 __ bind(&parameters_test); 2203 __ bind(&parameters_test);
2097 __ cmp(r6, Operand(Smi::FromInt(0))); 2204 __ CmpSmiLiteral(r9, Smi::FromInt(0), r0);
2098 __ b(ne, &parameters_loop); 2205 __ bne(&parameters_loop);
2099
2100 // Restore r0 = new object (tagged)
2101 __ sub(r0, r4, Operand(Heap::kSloppyArgumentsObjectSize));
2102 2206
2103 __ bind(&skip_parameter_map); 2207 __ bind(&skip_parameter_map);
2104 // r0 = address of new object (tagged) 2208 // r5 = argument count (tagged)
2105 // r2 = argument count (tagged) 2209 // r6 = address of backing store (tagged)
2106 // r3 = address of backing store (tagged) 2210 // r8 = scratch
2107 // r5 = scratch
2108 // Copy arguments header and remaining slots (if there are any). 2211 // Copy arguments header and remaining slots (if there are any).
2109 __ LoadRoot(r5, Heap::kFixedArrayMapRootIndex); 2212 __ LoadRoot(r8, Heap::kFixedArrayMapRootIndex);
2110 __ str(r5, FieldMemOperand(r3, FixedArray::kMapOffset)); 2213 __ StoreP(r8, FieldMemOperand(r6, FixedArray::kMapOffset), r0);
2111 __ str(r2, FieldMemOperand(r3, FixedArray::kLengthOffset)); 2214 __ StoreP(r5, FieldMemOperand(r6, FixedArray::kLengthOffset), r0);
2112 2215
2113 Label arguments_loop, arguments_test; 2216 Label arguments_loop, arguments_test;
2114 __ mov(r9, r1); 2217 __ mr(r11, r4);
2115 __ ldr(r4, MemOperand(sp, 1 * kPointerSize)); 2218 __ LoadP(r7, MemOperand(sp, 1 * kPointerSize));
2116 __ sub(r4, r4, Operand(r9, LSL, 1)); 2219 __ SmiToPtrArrayOffset(r8, r11);
2117 __ jmp(&arguments_test); 2220 __ sub(r7, r7, r8);
2221 __ b(&arguments_test);
2118 2222
2119 __ bind(&arguments_loop); 2223 __ bind(&arguments_loop);
2120 __ sub(r4, r4, Operand(kPointerSize)); 2224 __ subi(r7, r7, Operand(kPointerSize));
2121 __ ldr(r6, MemOperand(r4, 0)); 2225 __ LoadP(r9, MemOperand(r7, 0));
2122 __ add(r5, r3, Operand(r9, LSL, 1)); 2226 __ SmiToPtrArrayOffset(r8, r11);
2123 __ str(r6, FieldMemOperand(r5, FixedArray::kHeaderSize)); 2227 __ add(r8, r6, r8);
2124 __ add(r9, r9, Operand(Smi::FromInt(1))); 2228 __ StoreP(r9, FieldMemOperand(r8, FixedArray::kHeaderSize), r0);
2229 __ AddSmiLiteral(r11, r11, Smi::FromInt(1), r0);
2125 2230
2126 __ bind(&arguments_test); 2231 __ bind(&arguments_test);
2127 __ cmp(r9, Operand(r2)); 2232 __ cmp(r11, r5);
2128 __ b(lt, &arguments_loop); 2233 __ blt(&arguments_loop);
2129 2234
2130 // Return and remove the on-stack parameters. 2235 // Return and remove the on-stack parameters.
2131 __ add(sp, sp, Operand(3 * kPointerSize)); 2236 __ addi(sp, sp, Operand(3 * kPointerSize));
2132 __ Ret(); 2237 __ Ret();
2133 2238
2134 // Do the runtime call to allocate the arguments object. 2239 // Do the runtime call to allocate the arguments object.
2135 // r0 = address of new object (tagged) 2240 // r5 = argument count (tagged)
2136 // r2 = argument count (tagged)
2137 __ bind(&runtime); 2241 __ bind(&runtime);
2138 __ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. 2242 __ StoreP(r5, MemOperand(sp, 0 * kPointerSize)); // Patch argument count.
2139 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); 2243 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1);
2140 } 2244 }
2141 2245
2142 2246
2143 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 2247 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
2144 // sp[0] : number of parameters 2248 // sp[0] : number of parameters
2145 // sp[4] : receiver displacement 2249 // sp[4] : receiver displacement
2146 // sp[8] : function 2250 // sp[8] : function
2147 // Check if the calling frame is an arguments adaptor frame. 2251 // Check if the calling frame is an arguments adaptor frame.
2148 Label adaptor_frame, try_allocate, runtime; 2252 Label adaptor_frame, try_allocate, runtime;
2149 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2253 __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2150 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2254 __ LoadP(r6, MemOperand(r5, StandardFrameConstants::kContextOffset));
2151 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2255 STATIC_ASSERT(StackFrame::ARGUMENTS_ADAPTOR < 0x3fffu);
2152 __ b(eq, &adaptor_frame); 2256 __ CmpSmiLiteral(r6, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
2257 __ beq(&adaptor_frame);
2153 2258
2154 // Get the length from the frame. 2259 // Get the length from the frame.
2155 __ ldr(r1, MemOperand(sp, 0)); 2260 __ LoadP(r4, MemOperand(sp, 0));
2156 __ b(&try_allocate); 2261 __ b(&try_allocate);
2157 2262
2158 // Patch the arguments.length and the parameters pointer. 2263 // Patch the arguments.length and the parameters pointer.
2159 __ bind(&adaptor_frame); 2264 __ bind(&adaptor_frame);
2160 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2265 __ LoadP(r4, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
2161 __ str(r1, MemOperand(sp, 0)); 2266 __ StoreP(r4, MemOperand(sp, 0));
2162 __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1)); 2267 __ SmiToPtrArrayOffset(r6, r4);
2163 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); 2268 __ add(r6, r5, r6);
2164 __ str(r3, MemOperand(sp, 1 * kPointerSize)); 2269 __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
2270 __ StoreP(r6, MemOperand(sp, 1 * kPointerSize));
2165 2271
2166 // Try the new space allocation. Start out with computing the size 2272 // Try the new space allocation. Start out with computing the size
2167 // of the arguments object and the elements array in words. 2273 // of the arguments object and the elements array in words.
2168 Label add_arguments_object; 2274 Label add_arguments_object;
2169 __ bind(&try_allocate); 2275 __ bind(&try_allocate);
2170 __ SmiUntag(r1, SetCC); 2276 __ cmpi(r4, Operand::Zero());
2171 __ b(eq, &add_arguments_object); 2277 __ beq(&add_arguments_object);
2172 __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize)); 2278 __ SmiUntag(r4);
2279 __ addi(r4, r4, Operand(FixedArray::kHeaderSize / kPointerSize));
2173 __ bind(&add_arguments_object); 2280 __ bind(&add_arguments_object);
2174 __ add(r1, r1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize)); 2281 __ addi(r4, r4, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
2175 2282
2176 // Do the allocation of both objects in one go. 2283 // Do the allocation of both objects in one go.
2177 __ Allocate(r1, r0, r2, r3, &runtime, 2284 __ Allocate(r4, r3, r5, r6, &runtime,
2178 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS)); 2285 static_cast<AllocationFlags>(TAG_OBJECT | SIZE_IN_WORDS));
2179 2286
2180 // Get the arguments boilerplate from the current native context. 2287 // Get the arguments boilerplate from the current native context.
2181 __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 2288 __ LoadP(r7,
2182 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset)); 2289 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
2183 __ ldr(r4, MemOperand( 2290 __ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset));
2184 r4, Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX))); 2291 __ LoadP(r7, MemOperand(r7, Context::SlotOffset(
2292 Context::STRICT_ARGUMENTS_MAP_INDEX)));
2185 2293
2186 __ str(r4, FieldMemOperand(r0, JSObject::kMapOffset)); 2294 __ StoreP(r7, FieldMemOperand(r3, JSObject::kMapOffset), r0);
2187 __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex); 2295 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
2188 __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2296 __ StoreP(r6, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0);
2189 __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); 2297 __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
2190 2298
2191 // Get the length (smi tagged) and set that as an in-object property too. 2299 // Get the length (smi tagged) and set that as an in-object property too.
2192 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); 2300 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2193 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); 2301 __ LoadP(r4, MemOperand(sp, 0 * kPointerSize));
2194 __ AssertSmi(r1); 2302 __ AssertSmi(r4);
2195 __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + 2303 __ StoreP(r4, FieldMemOperand(r3, JSObject::kHeaderSize +
2196 Heap::kArgumentsLengthIndex * kPointerSize)); 2304 Heap::kArgumentsLengthIndex * kPointerSize),
2305 r0);
2197 2306
2198 // If there are no actual arguments, we're done. 2307 // If there are no actual arguments, we're done.
2199 Label done; 2308 Label done;
2200 __ cmp(r1, Operand::Zero()); 2309 __ cmpi(r4, Operand::Zero());
2201 __ b(eq, &done); 2310 __ beq(&done);
2202 2311
2203 // Get the parameters pointer from the stack. 2312 // Get the parameters pointer from the stack.
2204 __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); 2313 __ LoadP(r5, MemOperand(sp, 1 * kPointerSize));
2205 2314
2206 // Set up the elements pointer in the allocated arguments object and 2315 // Set up the elements pointer in the allocated arguments object and
2207 // initialize the header in the elements fixed array. 2316 // initialize the header in the elements fixed array.
2208 __ add(r4, r0, Operand(Heap::kStrictArgumentsObjectSize)); 2317 __ addi(r7, r3, Operand(Heap::kStrictArgumentsObjectSize));
2209 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 2318 __ StoreP(r7, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
2210 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex); 2319 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
2211 __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset)); 2320 __ StoreP(r6, FieldMemOperand(r7, FixedArray::kMapOffset), r0);
2212 __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset)); 2321 __ StoreP(r4, FieldMemOperand(r7, FixedArray::kLengthOffset), r0);
2213 __ SmiUntag(r1); 2322 // Untag the length for the loop.
2323 __ SmiUntag(r4);
2214 2324
2215 // Copy the fixed array slots. 2325 // Copy the fixed array slots.
2216 Label loop; 2326 Label loop;
2217 // Set up r4 to point to the first array slot. 2327 // Set up r7 to point to the first array slot.
2218 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 2328 __ addi(r7, r7, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2219 __ bind(&loop); 2329 __ bind(&loop);
2220 // Pre-decrement r2 with kPointerSize on each iteration. 2330 // Pre-decrement r5 with kPointerSize on each iteration.
2221 // Pre-decrement in order to skip receiver. 2331 // Pre-decrement in order to skip receiver.
2222 __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex)); 2332 __ LoadPU(r6, MemOperand(r5, -kPointerSize));
2223 // Post-increment r4 with kPointerSize on each iteration. 2333 // Post-increment r7 with kPointerSize on each iteration.
2224 __ str(r3, MemOperand(r4, kPointerSize, PostIndex)); 2334 __ StoreP(r6, MemOperand(r7));
2225 __ sub(r1, r1, Operand(1)); 2335 __ addi(r7, r7, Operand(kPointerSize));
2226 __ cmp(r1, Operand::Zero()); 2336 __ subi(r4, r4, Operand(1));
2227 __ b(ne, &loop); 2337 __ cmpi(r4, Operand::Zero());
2338 __ bne(&loop);
2228 2339
2229 // Return and remove the on-stack parameters. 2340 // Return and remove the on-stack parameters.
2230 __ bind(&done); 2341 __ bind(&done);
2231 __ add(sp, sp, Operand(3 * kPointerSize)); 2342 __ addi(sp, sp, Operand(3 * kPointerSize));
2232 __ Ret(); 2343 __ Ret();
2233 2344
2234 // Do the runtime call to allocate the arguments object. 2345 // Do the runtime call to allocate the arguments object.
2235 __ bind(&runtime); 2346 __ bind(&runtime);
2236 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); 2347 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1);
2237 } 2348 }
2238 2349
2239 2350
2240 void RegExpExecStub::Generate(MacroAssembler* masm) { 2351 void RegExpExecStub::Generate(MacroAssembler* masm) {
2241 // Just jump directly to runtime if native RegExp is not selected at compile 2352 // Just jump directly to runtime if native RegExp is not selected at compile
2242 // time or if regexp entry in generated code is turned off runtime switch or 2353 // time or if regexp entry in generated code is turned off runtime switch or
2243 // at compilation. 2354 // at compilation.
2244 #ifdef V8_INTERPRETED_REGEXP 2355 #ifdef V8_INTERPRETED_REGEXP
2245 __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 2356 __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1);
2246 #else // V8_INTERPRETED_REGEXP 2357 #else // V8_INTERPRETED_REGEXP
2247 2358
2248 // Stack frame on entry. 2359 // Stack frame on entry.
2249 // sp[0]: last_match_info (expected JSArray) 2360 // sp[0]: last_match_info (expected JSArray)
2250 // sp[4]: previous index 2361 // sp[4]: previous index
2251 // sp[8]: subject string 2362 // sp[8]: subject string
2252 // sp[12]: JSRegExp object 2363 // sp[12]: JSRegExp object
2253 2364
2254 const int kLastMatchInfoOffset = 0 * kPointerSize; 2365 const int kLastMatchInfoOffset = 0 * kPointerSize;
2255 const int kPreviousIndexOffset = 1 * kPointerSize; 2366 const int kPreviousIndexOffset = 1 * kPointerSize;
2256 const int kSubjectOffset = 2 * kPointerSize; 2367 const int kSubjectOffset = 2 * kPointerSize;
2257 const int kJSRegExpOffset = 3 * kPointerSize; 2368 const int kJSRegExpOffset = 3 * kPointerSize;
2258 2369
2259 Label runtime; 2370 Label runtime, br_over, encoding_type_UC16;
2371
2260 // Allocation of registers for this function. These are in callee save 2372 // Allocation of registers for this function. These are in callee save
2261 // registers and will be preserved by the call to the native RegExp code, as 2373 // registers and will be preserved by the call to the native RegExp code, as
2262 // this code is called using the normal C calling convention. When calling 2374 // this code is called using the normal C calling convention. When calling
2263 // directly from generated code the native RegExp code will not do a GC and 2375 // directly from generated code the native RegExp code will not do a GC and
2264 // therefore the content of these registers are safe to use after the call. 2376 // therefore the content of these registers are safe to use after the call.
2265 Register subject = r4; 2377 Register subject = r14;
2266 Register regexp_data = r5; 2378 Register regexp_data = r15;
2267 Register last_match_info_elements = no_reg; // will be r6; 2379 Register last_match_info_elements = r16;
2380 Register code = r17;
2381
2382 // Ensure register assigments are consistent with callee save masks
2383 ASSERT(subject.bit() & kCalleeSaved);
2384 ASSERT(regexp_data.bit() & kCalleeSaved);
2385 ASSERT(last_match_info_elements.bit() & kCalleeSaved);
2386 ASSERT(code.bit() & kCalleeSaved);
2268 2387
2269 // Ensure that a RegExp stack is allocated. 2388 // Ensure that a RegExp stack is allocated.
2270 ExternalReference address_of_regexp_stack_memory_address = 2389 ExternalReference address_of_regexp_stack_memory_address =
2271 ExternalReference::address_of_regexp_stack_memory_address(isolate()); 2390 ExternalReference::address_of_regexp_stack_memory_address(isolate());
2272 ExternalReference address_of_regexp_stack_memory_size = 2391 ExternalReference address_of_regexp_stack_memory_size =
2273 ExternalReference::address_of_regexp_stack_memory_size(isolate()); 2392 ExternalReference::address_of_regexp_stack_memory_size(isolate());
2274 __ mov(r0, Operand(address_of_regexp_stack_memory_size)); 2393 __ mov(r3, Operand(address_of_regexp_stack_memory_size));
2275 __ ldr(r0, MemOperand(r0, 0)); 2394 __ LoadP(r3, MemOperand(r3, 0));
2276 __ cmp(r0, Operand::Zero()); 2395 __ cmpi(r3, Operand::Zero());
2277 __ b(eq, &runtime); 2396 __ beq(&runtime);
2278 2397
2279 // Check that the first argument is a JSRegExp object. 2398 // Check that the first argument is a JSRegExp object.
2280 __ ldr(r0, MemOperand(sp, kJSRegExpOffset)); 2399 __ LoadP(r3, MemOperand(sp, kJSRegExpOffset));
2281 __ JumpIfSmi(r0, &runtime); 2400 __ JumpIfSmi(r3, &runtime);
2282 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 2401 __ CompareObjectType(r3, r4, r4, JS_REGEXP_TYPE);
2283 __ b(ne, &runtime); 2402 __ bne(&runtime);
2284 2403
2285 // Check that the RegExp has been compiled (data contains a fixed array). 2404 // Check that the RegExp has been compiled (data contains a fixed array).
2286 __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset)); 2405 __ LoadP(regexp_data, FieldMemOperand(r3, JSRegExp::kDataOffset));
2287 if (FLAG_debug_code) { 2406 if (FLAG_debug_code) {
2288 __ SmiTst(regexp_data); 2407 __ TestIfSmi(regexp_data, r0);
2289 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected); 2408 __ Check(ne, kUnexpectedTypeForRegExpDataFixedArrayExpected, cr0);
2290 __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE); 2409 __ CompareObjectType(regexp_data, r3, r3, FIXED_ARRAY_TYPE);
2291 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected); 2410 __ Check(eq, kUnexpectedTypeForRegExpDataFixedArrayExpected);
2292 } 2411 }
2293 2412
2294 // regexp_data: RegExp data (FixedArray) 2413 // regexp_data: RegExp data (FixedArray)
2295 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. 2414 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
2296 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); 2415 __ LoadP(r3, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
2297 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); 2416 // ASSERT(Smi::FromInt(JSRegExp::IRREGEXP) < (char *)0xffffu);
2298 __ b(ne, &runtime); 2417 __ CmpSmiLiteral(r3, Smi::FromInt(JSRegExp::IRREGEXP), r0);
2418 __ bne(&runtime);
2299 2419
2300 // regexp_data: RegExp data (FixedArray) 2420 // regexp_data: RegExp data (FixedArray)
2301 // Check that the number of captures fit in the static offsets vector buffer. 2421 // Check that the number of captures fit in the static offsets vector buffer.
2302 __ ldr(r2, 2422 __ LoadP(r5,
2303 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 2423 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
2304 // Check (number_of_captures + 1) * 2 <= offsets vector size 2424 // Check (number_of_captures + 1) * 2 <= offsets vector size
2305 // Or number_of_captures * 2 <= offsets vector size - 2 2425 // Or number_of_captures * 2 <= offsets vector size - 2
2306 // Multiplying by 2 comes for free since r2 is smi-tagged. 2426 // SmiToShortArrayOffset accomplishes the multiplication by 2 and
2307 STATIC_ASSERT(kSmiTag == 0); 2427 // SmiUntag (which is a nop for 32-bit).
2308 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 2428 __ SmiToShortArrayOffset(r5, r5);
2309 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2); 2429 STATIC_ASSERT(Isolate::kJSRegexpStaticOffsetsVectorSize >= 2);
2310 __ cmp(r2, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2)); 2430 __ cmpli(r5, Operand(Isolate::kJSRegexpStaticOffsetsVectorSize - 2));
2311 __ b(hi, &runtime); 2431 __ bgt(&runtime);
2312 2432
2313 // Reset offset for possibly sliced string. 2433 // Reset offset for possibly sliced string.
2314 __ mov(r9, Operand::Zero()); 2434 __ li(r11, Operand::Zero());
2315 __ ldr(subject, MemOperand(sp, kSubjectOffset)); 2435 __ LoadP(subject, MemOperand(sp, kSubjectOffset));
2316 __ JumpIfSmi(subject, &runtime); 2436 __ JumpIfSmi(subject, &runtime);
2317 __ mov(r3, subject); // Make a copy of the original subject string. 2437 __ mr(r6, subject); // Make a copy of the original subject string.
2318 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 2438 __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
2319 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 2439 __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
2320 // subject: subject string 2440 // subject: subject string
2321 // r3: subject string 2441 // r6: subject string
2322 // r0: subject string instance type 2442 // r3: subject string instance type
2323 // regexp_data: RegExp data (FixedArray) 2443 // regexp_data: RegExp data (FixedArray)
2324 // Handle subject string according to its encoding and representation: 2444 // Handle subject string according to its encoding and representation:
2325 // (1) Sequential string? If yes, go to (5). 2445 // (1) Sequential string? If yes, go to (5).
2326 // (2) Anything but sequential or cons? If yes, go to (6). 2446 // (2) Anything but sequential or cons? If yes, go to (6).
2327 // (3) Cons string. If the string is flat, replace subject with first string. 2447 // (3) Cons string. If the string is flat, replace subject with first string.
2328 // Otherwise bailout. 2448 // Otherwise bailout.
2329 // (4) Is subject external? If yes, go to (7). 2449 // (4) Is subject external? If yes, go to (7).
2330 // (5) Sequential string. Load regexp code according to encoding. 2450 // (5) Sequential string. Load regexp code according to encoding.
2331 // (E) Carry on. 2451 // (E) Carry on.
2332 /// [...] 2452 /// [...]
2333 2453
2334 // Deferred code at the end of the stub: 2454 // Deferred code at the end of the stub:
2335 // (6) Not a long external string? If yes, go to (8). 2455 // (6) Not a long external string? If yes, go to (8).
2336 // (7) External string. Make it, offset-wise, look like a sequential string. 2456 // (7) External string. Make it, offset-wise, look like a sequential string.
2337 // Go to (5). 2457 // Go to (5).
2338 // (8) Short external string or not a string? If yes, bail out to runtime. 2458 // (8) Short external string or not a string? If yes, bail out to runtime.
2339 // (9) Sliced string. Replace subject with parent. Go to (4). 2459 // (9) Sliced string. Replace subject with parent. Go to (4).
2340 2460
2341 Label seq_string /* 5 */, external_string /* 7 */, 2461 Label seq_string /* 5 */, external_string /* 7 */,
2342 check_underlying /* 4 */, not_seq_nor_cons /* 6 */, 2462 check_underlying /* 4 */, not_seq_nor_cons /* 6 */,
2343 not_long_external /* 8 */; 2463 not_long_external /* 8 */;
2344 2464
2345 // (1) Sequential string? If yes, go to (5). 2465 // (1) Sequential string? If yes, go to (5).
2346 __ and_(r1, 2466 STATIC_ASSERT((kIsNotStringMask |
2347 r0, 2467 kStringRepresentationMask |
2468 kShortExternalStringMask) == 0x93);
2469 __ andi(r4,
2470 r3,
2348 Operand(kIsNotStringMask | 2471 Operand(kIsNotStringMask |
2349 kStringRepresentationMask | 2472 kStringRepresentationMask |
2350 kShortExternalStringMask), 2473 kShortExternalStringMask));
2351 SetCC);
2352 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 2474 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
2353 __ b(eq, &seq_string); // Go to (5). 2475 __ beq(&seq_string, cr0); // Go to (5).
2354 2476
2355 // (2) Anything but sequential or cons? If yes, go to (6). 2477 // (2) Anything but sequential or cons? If yes, go to (6).
2356 STATIC_ASSERT(kConsStringTag < kExternalStringTag); 2478 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
2357 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag); 2479 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
2358 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag); 2480 STATIC_ASSERT(kIsNotStringMask > kExternalStringTag);
2359 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag); 2481 STATIC_ASSERT(kShortExternalStringTag > kExternalStringTag);
2360 __ cmp(r1, Operand(kExternalStringTag)); 2482 STATIC_ASSERT(kExternalStringTag < 0xffffu);
2361 __ b(ge, &not_seq_nor_cons); // Go to (6). 2483 __ cmpi(r4, Operand(kExternalStringTag));
2484 __ bge(&not_seq_nor_cons); // Go to (6).
2362 2485
2363 // (3) Cons string. Check that it's flat. 2486 // (3) Cons string. Check that it's flat.
2364 // Replace subject with first string and reload instance type. 2487 // Replace subject with first string and reload instance type.
2365 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); 2488 __ LoadP(r3, FieldMemOperand(subject, ConsString::kSecondOffset));
2366 __ CompareRoot(r0, Heap::kempty_stringRootIndex); 2489 __ CompareRoot(r3, Heap::kempty_stringRootIndex);
2367 __ b(ne, &runtime); 2490 __ bne(&runtime);
2368 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 2491 __ LoadP(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
2369 2492
2370 // (4) Is subject external? If yes, go to (7). 2493 // (4) Is subject external? If yes, go to (7).
2371 __ bind(&check_underlying); 2494 __ bind(&check_underlying);
2372 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 2495 __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
2373 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 2496 __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
2374 STATIC_ASSERT(kSeqStringTag == 0); 2497 STATIC_ASSERT(kSeqStringTag == 0);
2375 __ tst(r0, Operand(kStringRepresentationMask)); 2498 STATIC_ASSERT(kStringRepresentationMask == 3);
2499 __ andi(r0, r3, Operand(kStringRepresentationMask));
2376 // The underlying external string is never a short external string. 2500 // The underlying external string is never a short external string.
2377 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength); 2501 STATIC_ASSERT(ExternalString::kMaxShortLength < ConsString::kMinLength);
2378 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength); 2502 STATIC_ASSERT(ExternalString::kMaxShortLength < SlicedString::kMinLength);
2379 __ b(ne, &external_string); // Go to (7). 2503 __ bne(&external_string, cr0); // Go to (7).
2380 2504
2381 // (5) Sequential string. Load regexp code according to encoding. 2505 // (5) Sequential string. Load regexp code according to encoding.
2382 __ bind(&seq_string); 2506 __ bind(&seq_string);
2383 // subject: sequential subject string (or look-alike, external string) 2507 // subject: sequential subject string (or look-alike, external string)
2384 // r3: original subject string 2508 // r6: original subject string
2385 // Load previous index and check range before r3 is overwritten. We have to 2509 // Load previous index and check range before r6 is overwritten. We have to
2386 // use r3 instead of subject here because subject might have been only made 2510 // use r6 instead of subject here because subject might have been only made
2387 // to look like a sequential string when it actually is an external string. 2511 // to look like a sequential string when it actually is an external string.
2388 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); 2512 __ LoadP(r4, MemOperand(sp, kPreviousIndexOffset));
2389 __ JumpIfNotSmi(r1, &runtime); 2513 __ JumpIfNotSmi(r4, &runtime);
2390 __ ldr(r3, FieldMemOperand(r3, String::kLengthOffset)); 2514 __ LoadP(r6, FieldMemOperand(r6, String::kLengthOffset));
2391 __ cmp(r3, Operand(r1)); 2515 __ cmpl(r6, r4);
2392 __ b(ls, &runtime); 2516 __ ble(&runtime);
2393 __ SmiUntag(r1); 2517 __ SmiUntag(r4);
2394 2518
2395 STATIC_ASSERT(4 == kOneByteStringTag); 2519 STATIC_ASSERT(4 == kOneByteStringTag);
2396 STATIC_ASSERT(kTwoByteStringTag == 0); 2520 STATIC_ASSERT(kTwoByteStringTag == 0);
2397 __ and_(r0, r0, Operand(kStringEncodingMask)); 2521 STATIC_ASSERT(kStringEncodingMask == 4);
2398 __ mov(r3, Operand(r0, ASR, 2), SetCC); 2522 __ ExtractBitMask(r6, r3, kStringEncodingMask, SetRC);
2399 __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); 2523 __ beq(&encoding_type_UC16, cr0);
2400 __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); 2524 __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset));
2525 __ b(&br_over);
2526 __ bind(&encoding_type_UC16);
2527 __ LoadP(code, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
2528 __ bind(&br_over);
2401 2529
2402 // (E) Carry on. String handling is done. 2530 // (E) Carry on. String handling is done.
2403 // r6: irregexp code 2531 // code: irregexp code
2404 // Check that the irregexp code has been generated for the actual string 2532 // Check that the irregexp code has been generated for the actual string
2405 // encoding. If it has, the field contains a code object otherwise it contains 2533 // encoding. If it has, the field contains a code object otherwise it contains
2406 // a smi (code flushing support). 2534 // a smi (code flushing support).
2407 __ JumpIfSmi(r6, &runtime); 2535 __ JumpIfSmi(code, &runtime);
2408 2536
2409 // r1: previous index 2537 // r4: previous index
2410 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); 2538 // r6: encoding of subject string (1 if ASCII, 0 if two_byte);
2411 // r6: code 2539 // code: Address of generated regexp code
2412 // subject: Subject string 2540 // subject: Subject string
2413 // regexp_data: RegExp data (FixedArray) 2541 // regexp_data: RegExp data (FixedArray)
2414 // All checks done. Now push arguments for native regexp code. 2542 // All checks done. Now push arguments for native regexp code.
2415 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r0, r2); 2543 __ IncrementCounter(isolate()->counters()->regexp_entry_native(), 1, r3, r5);
2416 2544
2417 // Isolates: note we add an additional parameter here (isolate pointer). 2545 // Isolates: note we add an additional parameter here (isolate pointer).
2418 const int kRegExpExecuteArguments = 9; 2546 const int kRegExpExecuteArguments = 10;
2419 const int kParameterRegisters = 4; 2547 const int kParameterRegisters = 8;
2420 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); 2548 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
2421 2549
2422 // Stack pointer now points to cell where return address is to be written. 2550 // Stack pointer now points to cell where return address is to be written.
2423 // Arguments are before that on the stack or in registers. 2551 // Arguments are before that on the stack or in registers.
2424 2552
2425 // Argument 9 (sp[20]): Pass current isolate address. 2553 // Argument 10 (in stack parameter area): Pass current isolate address.
2426 __ mov(r0, Operand(ExternalReference::isolate_address(isolate()))); 2554 __ mov(r3, Operand(ExternalReference::isolate_address(isolate())));
2427 __ str(r0, MemOperand(sp, 5 * kPointerSize)); 2555 __ StoreP(r3, MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize));
2428 2556
2429 // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript. 2557 // Argument 9 is a dummy that reserves the space used for
2430 __ mov(r0, Operand(1)); 2558 // the return address added by the ExitFrame in native calls.
2431 __ str(r0, MemOperand(sp, 4 * kPointerSize)); 2559
2432 2560 // Argument 8 (r10): Indicate that this is a direct call from JavaScript.
2433 // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area. 2561 __ li(r10, Operand(1));
2434 __ mov(r0, Operand(address_of_regexp_stack_memory_address)); 2562
2435 __ ldr(r0, MemOperand(r0, 0)); 2563 // Argument 7 (r9): Start (high end) of backtracking stack memory area.
2436 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); 2564 __ mov(r3, Operand(address_of_regexp_stack_memory_address));
2437 __ ldr(r2, MemOperand(r2, 0)); 2565 __ LoadP(r3, MemOperand(r3, 0));
2438 __ add(r0, r0, Operand(r2)); 2566 __ mov(r5, Operand(address_of_regexp_stack_memory_size));
2439 __ str(r0, MemOperand(sp, 3 * kPointerSize)); 2567 __ LoadP(r5, MemOperand(r5, 0));
2440 2568 __ add(r9, r3, r5);
2441 // Argument 6: Set the number of capture registers to zero to force global 2569
2442 // regexps to behave as non-global. This does not affect non-global regexps. 2570 // Argument 6 (r8): Set the number of capture registers to zero to force
2443 __ mov(r0, Operand::Zero()); 2571 // global egexps to behave as non-global. This does not affect non-global
2444 __ str(r0, MemOperand(sp, 2 * kPointerSize)); 2572 // regexps.
2445 2573 __ li(r8, Operand::Zero());
2446 // Argument 5 (sp[4]): static offsets vector buffer. 2574
2447 __ mov(r0, 2575 // Argument 5 (r7): static offsets vector buffer.
2576 __ mov(r7,
2448 Operand(ExternalReference::address_of_static_offsets_vector( 2577 Operand(ExternalReference::address_of_static_offsets_vector(
2449 isolate()))); 2578 isolate())));
2450 __ str(r0, MemOperand(sp, 1 * kPointerSize)); 2579
2451 2580 // For arguments 4 (r6) and 3 (r5) get string length, calculate start of
2452 // For arguments 4 and 3 get string length, calculate start of string data and 2581 // string data and calculate the shift of the index (0 for ASCII and 1 for
2453 // calculate the shift of the index (0 for ASCII and 1 for two byte). 2582 // two byte).
2454 __ add(r7, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag)); 2583 __ addi(r18, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
2455 __ eor(r3, r3, Operand(1)); 2584 __ xori(r6, r6, Operand(1));
2456 // Load the length from the original subject string from the previous stack 2585 // Load the length from the original subject string from the previous stack
2457 // frame. Therefore we have to use fp, which points exactly to two pointer 2586 // frame. Therefore we have to use fp, which points exactly to two pointer
2458 // sizes below the previous sp. (Because creating a new stack frame pushes 2587 // sizes below the previous sp. (Because creating a new stack frame pushes
2459 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) 2588 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
2460 __ ldr(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); 2589 __ LoadP(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
2461 // If slice offset is not 0, load the length from the original sliced string. 2590 // If slice offset is not 0, load the length from the original sliced string.
2462 // Argument 4, r3: End of string data 2591 // Argument 4, r6: End of string data
2463 // Argument 3, r2: Start of string data 2592 // Argument 3, r5: Start of string data
2464 // Prepare start and end index of the input. 2593 // Prepare start and end index of the input.
2465 __ add(r9, r7, Operand(r9, LSL, r3)); 2594 __ ShiftLeft(r11, r11, r6);
2466 __ add(r2, r9, Operand(r1, LSL, r3)); 2595 __ add(r11, r18, r11);
2467 2596 __ ShiftLeft(r5, r4, r6);
2468 __ ldr(r7, FieldMemOperand(subject, String::kLengthOffset)); 2597 __ add(r5, r11, r5);
2469 __ SmiUntag(r7); 2598
2470 __ add(r3, r9, Operand(r7, LSL, r3)); 2599 __ LoadP(r18, FieldMemOperand(subject, String::kLengthOffset));
2471 2600 __ SmiUntag(r18);
2472 // Argument 2 (r1): Previous index. 2601 __ ShiftLeft(r6, r18, r6);
2602 __ add(r6, r11, r6);
2603
2604 // Argument 2 (r4): Previous index.
2473 // Already there 2605 // Already there
2474 2606
2475 // Argument 1 (r0): Subject string. 2607 // Argument 1 (r3): Subject string.
2476 __ mov(r0, subject); 2608 __ mr(r3, subject);
2477 2609
2478 // Locate the code entry and call it. 2610 // Locate the code entry and call it.
2479 __ add(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag)); 2611 __ addi(code, code, Operand(Code::kHeaderSize - kHeapObjectTag));
2612
2613
2614 #if ABI_USES_FUNCTION_DESCRIPTORS && defined(USE_SIMULATOR)
2615 // Even Simulated AIX/PPC64 Linux uses a function descriptor for the
2616 // RegExp routine. Extract the instruction address here since
2617 // DirectCEntryStub::GenerateCall will not do it for calls out to
2618 // what it thinks is C code compiled for the simulator/host
2619 // platform.
2620 __ LoadP(code, MemOperand(code, 0)); // Instruction address
2621 #endif
2622
2480 DirectCEntryStub stub(isolate()); 2623 DirectCEntryStub stub(isolate());
2481 stub.GenerateCall(masm, r6); 2624 stub.GenerateCall(masm, code);
2482 2625
2483 __ LeaveExitFrame(false, no_reg, true); 2626 __ LeaveExitFrame(false, no_reg, true);
2484 2627
2485 last_match_info_elements = r6; 2628 // r3: result
2486
2487 // r0: result
2488 // subject: subject string (callee saved) 2629 // subject: subject string (callee saved)
2489 // regexp_data: RegExp data (callee saved) 2630 // regexp_data: RegExp data (callee saved)
2490 // last_match_info_elements: Last match info elements (callee saved) 2631 // last_match_info_elements: Last match info elements (callee saved)
2491 // Check the result. 2632 // Check the result.
2492 Label success; 2633 Label success;
2493 __ cmp(r0, Operand(1)); 2634 __ cmpi(r3, Operand(1));
2494 // We expect exactly one result since we force the called regexp to behave 2635 // We expect exactly one result since we force the called regexp to behave
2495 // as non-global. 2636 // as non-global.
2496 __ b(eq, &success); 2637 __ beq(&success);
2497 Label failure; 2638 Label failure;
2498 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); 2639 __ cmpi(r3, Operand(NativeRegExpMacroAssembler::FAILURE));
2499 __ b(eq, &failure); 2640 __ beq(&failure);
2500 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 2641 __ cmpi(r3, Operand(NativeRegExpMacroAssembler::EXCEPTION));
2501 // If not exception it can only be retry. Handle that in the runtime system. 2642 // If not exception it can only be retry. Handle that in the runtime system.
2502 __ b(ne, &runtime); 2643 __ bne(&runtime);
2503 // Result must now be exception. If there is no pending exception already a 2644 // Result must now be exception. If there is no pending exception already a
2504 // stack overflow (on the backtrack stack) was detected in RegExp code but 2645 // stack overflow (on the backtrack stack) was detected in RegExp code but
2505 // haven't created the exception yet. Handle that in the runtime system. 2646 // haven't created the exception yet. Handle that in the runtime system.
2506 // TODO(592): Rerunning the RegExp to get the stack overflow exception. 2647 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
2507 __ mov(r1, Operand(isolate()->factory()->the_hole_value())); 2648 __ mov(r4, Operand(isolate()->factory()->the_hole_value()));
2508 __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 2649 __ mov(r5, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
2509 isolate()))); 2650 isolate())));
2510 __ ldr(r0, MemOperand(r2, 0)); 2651 __ LoadP(r3, MemOperand(r5, 0));
2511 __ cmp(r0, r1); 2652 __ cmp(r3, r4);
2512 __ b(eq, &runtime); 2653 __ beq(&runtime);
2513 2654
2514 __ str(r1, MemOperand(r2, 0)); // Clear pending exception. 2655 __ StoreP(r4, MemOperand(r5, 0)); // Clear pending exception.
2515 2656
2516 // Check if the exception is a termination. If so, throw as uncatchable. 2657 // Check if the exception is a termination. If so, throw as uncatchable.
2517 __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex); 2658 __ CompareRoot(r3, Heap::kTerminationExceptionRootIndex);
2518 2659
2519 Label termination_exception; 2660 Label termination_exception;
2520 __ b(eq, &termination_exception); 2661 __ beq(&termination_exception);
2521 2662
2522 __ Throw(r0); 2663 __ Throw(r3);
2523 2664
2524 __ bind(&termination_exception); 2665 __ bind(&termination_exception);
2525 __ ThrowUncatchable(r0); 2666 __ ThrowUncatchable(r3);
2526 2667
2527 __ bind(&failure); 2668 __ bind(&failure);
2528 // For failure and exception return null. 2669 // For failure and exception return null.
2529 __ mov(r0, Operand(isolate()->factory()->null_value())); 2670 __ mov(r3, Operand(isolate()->factory()->null_value()));
2530 __ add(sp, sp, Operand(4 * kPointerSize)); 2671 __ addi(sp, sp, Operand(4 * kPointerSize));
2531 __ Ret(); 2672 __ Ret();
2532 2673
2533 // Process the result from the native regexp code. 2674 // Process the result from the native regexp code.
2534 __ bind(&success); 2675 __ bind(&success);
2535 __ ldr(r1, 2676 __ LoadP(r4,
2536 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); 2677 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset));
2537 // Calculate number of capture registers (number_of_captures + 1) * 2. 2678 // Calculate number of capture registers (number_of_captures + 1) * 2.
2538 // Multiplying by 2 comes for free since r1 is smi-tagged. 2679 // SmiToShortArrayOffset accomplishes the multiplication by 2 and
2539 STATIC_ASSERT(kSmiTag == 0); 2680 // SmiUntag (which is a nop for 32-bit).
2540 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); 2681 __ SmiToShortArrayOffset(r4, r4);
2541 __ add(r1, r1, Operand(2)); // r1 was a smi. 2682 __ addi(r4, r4, Operand(2));
2542 2683
2543 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); 2684 __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset));
2544 __ JumpIfSmi(r0, &runtime); 2685 __ JumpIfSmi(r3, &runtime);
2545 __ CompareObjectType(r0, r2, r2, JS_ARRAY_TYPE); 2686 __ CompareObjectType(r3, r5, r5, JS_ARRAY_TYPE);
2546 __ b(ne, &runtime); 2687 __ bne(&runtime);
2547 // Check that the JSArray is in fast case. 2688 // Check that the JSArray is in fast case.
2548 __ ldr(last_match_info_elements, 2689 __ LoadP(last_match_info_elements,
2549 FieldMemOperand(r0, JSArray::kElementsOffset)); 2690 FieldMemOperand(r3, JSArray::kElementsOffset));
2550 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 2691 __ LoadP(r3,
2551 __ CompareRoot(r0, Heap::kFixedArrayMapRootIndex); 2692 FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
2552 __ b(ne, &runtime); 2693 __ CompareRoot(r3, Heap::kFixedArrayMapRootIndex);
2694 __ bne(&runtime);
2553 // Check that the last match info has space for the capture registers and the 2695 // Check that the last match info has space for the capture registers and the
2554 // additional information. 2696 // additional information.
2555 __ ldr(r0, 2697 __ LoadP(r3,
2556 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 2698 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
2557 __ add(r2, r1, Operand(RegExpImpl::kLastMatchOverhead)); 2699 __ addi(r5, r4, Operand(RegExpImpl::kLastMatchOverhead));
2558 __ cmp(r2, Operand::SmiUntag(r0)); 2700 __ SmiUntag(r0, r3);
2559 __ b(gt, &runtime); 2701 __ cmp(r5, r0);
2560 2702 __ bgt(&runtime);
2561 // r1: number of capture registers 2703
2562 // r4: subject string 2704 // r4: number of capture registers
2705 // subject: subject string
2563 // Store the capture count. 2706 // Store the capture count.
2564 __ SmiTag(r2, r1); 2707 __ SmiTag(r5, r4);
2565 __ str(r2, FieldMemOperand(last_match_info_elements, 2708 __ StoreP(r5, FieldMemOperand(last_match_info_elements,
2566 RegExpImpl::kLastCaptureCountOffset)); 2709 RegExpImpl::kLastCaptureCountOffset), r0);
2567 // Store last subject and last input. 2710 // Store last subject and last input.
2568 __ str(subject, 2711 __ StoreP(subject,
2569 FieldMemOperand(last_match_info_elements, 2712 FieldMemOperand(last_match_info_elements,
2570 RegExpImpl::kLastSubjectOffset)); 2713 RegExpImpl::kLastSubjectOffset), r0);
2571 __ mov(r2, subject); 2714 __ mr(r5, subject);
2572 __ RecordWriteField(last_match_info_elements, 2715 __ RecordWriteField(last_match_info_elements,
2573 RegExpImpl::kLastSubjectOffset, 2716 RegExpImpl::kLastSubjectOffset,
2574 subject, 2717 subject,
2575 r3, 2718 r10,
2576 kLRHasNotBeenSaved, 2719 kLRHasNotBeenSaved,
2577 kDontSaveFPRegs); 2720 kDontSaveFPRegs);
2578 __ mov(subject, r2); 2721 __ mr(subject, r5);
2579 __ str(subject, 2722 __ StoreP(subject,
2580 FieldMemOperand(last_match_info_elements, 2723 FieldMemOperand(last_match_info_elements,
2581 RegExpImpl::kLastInputOffset)); 2724 RegExpImpl::kLastInputOffset), r0);
2582 __ RecordWriteField(last_match_info_elements, 2725 __ RecordWriteField(last_match_info_elements,
2583 RegExpImpl::kLastInputOffset, 2726 RegExpImpl::kLastInputOffset,
2584 subject, 2727 subject,
2585 r3, 2728 r10,
2586 kLRHasNotBeenSaved, 2729 kLRHasNotBeenSaved,
2587 kDontSaveFPRegs); 2730 kDontSaveFPRegs);
2588 2731
2589 // Get the static offsets vector filled by the native regexp code. 2732 // Get the static offsets vector filled by the native regexp code.
2590 ExternalReference address_of_static_offsets_vector = 2733 ExternalReference address_of_static_offsets_vector =
2591 ExternalReference::address_of_static_offsets_vector(isolate()); 2734 ExternalReference::address_of_static_offsets_vector(isolate());
2592 __ mov(r2, Operand(address_of_static_offsets_vector)); 2735 __ mov(r5, Operand(address_of_static_offsets_vector));
2593 2736
2594 // r1: number of capture registers 2737 // r4: number of capture registers
2595 // r2: offsets vector 2738 // r5: offsets vector
2596 Label next_capture, done; 2739 Label next_capture;
2597 // Capture register counter starts from number of capture registers and 2740 // Capture register counter starts from number of capture registers and
2598 // counts down until wraping after zero. 2741 // counts down until wraping after zero.
2599 __ add(r0, 2742 __ addi(r3,
2600 last_match_info_elements, 2743 last_match_info_elements,
2601 Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag)); 2744 Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag -
2745 kPointerSize));
2746 __ addi(r5, r5, Operand(-kIntSize)); // bias down for lwzu
2747 __ mtctr(r4);
2602 __ bind(&next_capture); 2748 __ bind(&next_capture);
2603 __ sub(r1, r1, Operand(1), SetCC);
2604 __ b(mi, &done);
2605 // Read the value from the static offsets vector buffer. 2749 // Read the value from the static offsets vector buffer.
2606 __ ldr(r3, MemOperand(r2, kPointerSize, PostIndex)); 2750 __ lwzu(r6, MemOperand(r5, kIntSize));
2607 // Store the smi value in the last match info. 2751 // Store the smi value in the last match info.
2608 __ SmiTag(r3); 2752 __ SmiTag(r6);
2609 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); 2753 __ StorePU(r6, MemOperand(r3, kPointerSize));
2610 __ jmp(&next_capture); 2754 __ bdnz(&next_capture);
2611 __ bind(&done);
2612 2755
2613 // Return last match info. 2756 // Return last match info.
2614 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); 2757 __ LoadP(r3, MemOperand(sp, kLastMatchInfoOffset));
2615 __ add(sp, sp, Operand(4 * kPointerSize)); 2758 __ addi(sp, sp, Operand(4 * kPointerSize));
2616 __ Ret(); 2759 __ Ret();
2617 2760
2618 // Do the runtime call to execute the regexp. 2761 // Do the runtime call to execute the regexp.
2619 __ bind(&runtime); 2762 __ bind(&runtime);
2620 __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1); 2763 __ TailCallRuntime(Runtime::kRegExpExecRT, 4, 1);
2621 2764
2622 // Deferred code for string handling. 2765 // Deferred code for string handling.
2623 // (6) Not a long external string? If yes, go to (8). 2766 // (6) Not a long external string? If yes, go to (8).
2624 __ bind(&not_seq_nor_cons); 2767 __ bind(&not_seq_nor_cons);
2625 // Compare flags are still set. 2768 // Compare flags are still set.
2626 __ b(gt, &not_long_external); // Go to (8). 2769 __ bgt(&not_long_external); // Go to (8).
2627 2770
2628 // (7) External string. Make it, offset-wise, look like a sequential string. 2771 // (7) External string. Make it, offset-wise, look like a sequential string.
2629 __ bind(&external_string); 2772 __ bind(&external_string);
2630 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); 2773 __ LoadP(r3, FieldMemOperand(subject, HeapObject::kMapOffset));
2631 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 2774 __ lbz(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
2632 if (FLAG_debug_code) { 2775 if (FLAG_debug_code) {
2633 // Assert that we do not have a cons or slice (indirect strings) here. 2776 // Assert that we do not have a cons or slice (indirect strings) here.
2634 // Sequential strings have already been ruled out. 2777 // Sequential strings have already been ruled out.
2635 __ tst(r0, Operand(kIsIndirectStringMask)); 2778 STATIC_ASSERT(kIsIndirectStringMask == 1);
2636 __ Assert(eq, kExternalStringExpectedButNotFound); 2779 __ andi(r0, r3, Operand(kIsIndirectStringMask));
2780 __ Assert(eq, kExternalStringExpectedButNotFound, cr0);
2637 } 2781 }
2638 __ ldr(subject, 2782 __ LoadP(subject,
2639 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); 2783 FieldMemOperand(subject, ExternalString::kResourceDataOffset));
2640 // Move the pointer so that offset-wise, it looks like a sequential string. 2784 // Move the pointer so that offset-wise, it looks like a sequential string.
2641 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 2785 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2642 __ sub(subject, 2786 __ subi(subject,
2643 subject, 2787 subject,
2644 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 2788 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2645 __ jmp(&seq_string); // Go to (5). 2789 __ b(&seq_string); // Go to (5).
2646 2790
2647 // (8) Short external string or not a string? If yes, bail out to runtime. 2791 // (8) Short external string or not a string? If yes, bail out to runtime.
2648 __ bind(&not_long_external); 2792 __ bind(&not_long_external);
2649 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0); 2793 STATIC_ASSERT(kNotStringTag != 0 && kShortExternalStringTag !=0);
2650 __ tst(r1, Operand(kIsNotStringMask | kShortExternalStringMask)); 2794 __ andi(r0, r4, Operand(kIsNotStringMask | kShortExternalStringMask));
2651 __ b(ne, &runtime); 2795 __ bne(&runtime, cr0);
2652 2796
2653 // (9) Sliced string. Replace subject with parent. Go to (4). 2797 // (9) Sliced string. Replace subject with parent. Go to (4).
2654 // Load offset into r9 and replace subject string with parent. 2798 // Load offset into r11 and replace subject string with parent.
2655 __ ldr(r9, FieldMemOperand(subject, SlicedString::kOffsetOffset)); 2799 __ LoadP(r11, FieldMemOperand(subject, SlicedString::kOffsetOffset));
2656 __ SmiUntag(r9); 2800 __ SmiUntag(r11);
2657 __ ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); 2801 __ LoadP(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
2658 __ jmp(&check_underlying); // Go to (4). 2802 __ b(&check_underlying); // Go to (4).
2659 #endif // V8_INTERPRETED_REGEXP 2803 #endif // V8_INTERPRETED_REGEXP
2660 } 2804 }
2661 2805
2662 2806
2663 static void GenerateRecordCallTarget(MacroAssembler* masm) { 2807 static void GenerateRecordCallTarget(MacroAssembler* masm) {
2664 // Cache the called function in a feedback vector slot. Cache states 2808 // Cache the called function in a feedback vector slot. Cache states
2665 // are uninitialized, monomorphic (indicated by a JSFunction), and 2809 // are uninitialized, monomorphic (indicated by a JSFunction), and
2666 // megamorphic. 2810 // megamorphic.
2667 // r0 : number of arguments to the construct function 2811 // r3 : number of arguments to the construct function
2668 // r1 : the function to call 2812 // r4 : the function to call
2669 // r2 : Feedback vector 2813 // r5 : Feedback vector
2670 // r3 : slot in feedback vector (Smi) 2814 // r6 : slot in feedback vector (Smi)
2671 Label initialize, done, miss, megamorphic, not_array_function; 2815 Label initialize, done, miss, megamorphic, not_array_function;
2672 2816
2673 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), 2817 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()),
2674 masm->isolate()->heap()->megamorphic_symbol()); 2818 masm->isolate()->heap()->megamorphic_symbol());
2675 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), 2819 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()),
2676 masm->isolate()->heap()->uninitialized_symbol()); 2820 masm->isolate()->heap()->uninitialized_symbol());
2677 2821
2678 // Load the cache state into r4. 2822 // Load the cache state into r7.
2679 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); 2823 __ SmiToPtrArrayOffset(r7, r6);
2680 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); 2824 __ add(r7, r5, r7);
2825 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize));
2681 2826
2682 // A monomorphic cache hit or an already megamorphic state: invoke the 2827 // A monomorphic cache hit or an already megamorphic state: invoke the
2683 // function without changing the state. 2828 // function without changing the state.
2684 __ cmp(r4, r1); 2829 __ cmp(r7, r4);
2685 __ b(eq, &done); 2830 __ b(eq, &done);
2686 2831
2687 if (!FLAG_pretenuring_call_new) { 2832 if (!FLAG_pretenuring_call_new) {
2688 // If we came here, we need to see if we are the array function. 2833 // If we came here, we need to see if we are the array function.
2689 // If we didn't have a matching function, and we didn't find the megamorph 2834 // If we didn't have a matching function, and we didn't find the megamorph
2690 // sentinel, then we have in the slot either some other function or an 2835 // sentinel, then we have in the slot either some other function or an
2691 // AllocationSite. Do a map check on the object in ecx. 2836 // AllocationSite. Do a map check on the object in ecx.
2692 __ ldr(r5, FieldMemOperand(r4, 0)); 2837 __ LoadP(r8, FieldMemOperand(r7, 0));
2693 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); 2838 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
2694 __ b(ne, &miss); 2839 __ bne(&miss);
2695 2840
2696 // Make sure the function is the Array() function 2841 // Make sure the function is the Array() function
2697 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); 2842 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7);
2698 __ cmp(r1, r4); 2843 __ cmp(r4, r7);
2699 __ b(ne, &megamorphic); 2844 __ bne(&megamorphic);
2700 __ jmp(&done); 2845 __ b(&done);
2701 } 2846 }
2702 2847
2703 __ bind(&miss); 2848 __ bind(&miss);
2704 2849
2705 // A monomorphic miss (i.e, here the cache is not uninitialized) goes 2850 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
2706 // megamorphic. 2851 // megamorphic.
2707 __ CompareRoot(r4, Heap::kUninitializedSymbolRootIndex); 2852 __ CompareRoot(r7, Heap::kUninitializedSymbolRootIndex);
2708 __ b(eq, &initialize); 2853 __ beq(&initialize);
2709 // MegamorphicSentinel is an immortal immovable object (undefined) so no 2854 // MegamorphicSentinel is an immortal immovable object (undefined) so no
2710 // write-barrier is needed. 2855 // write-barrier is needed.
2711 __ bind(&megamorphic); 2856 __ bind(&megamorphic);
2712 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); 2857 __ SmiToPtrArrayOffset(r7, r6);
2858 __ add(r7, r5, r7);
2713 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); 2859 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex);
2714 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); 2860 __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0);
2715 __ jmp(&done); 2861 __ jmp(&done);
2716 2862
2717 // An uninitialized cache is patched with the function 2863 // An uninitialized cache is patched with the function
2718 __ bind(&initialize); 2864 __ bind(&initialize);
2719 2865
2720 if (!FLAG_pretenuring_call_new) { 2866 if (!FLAG_pretenuring_call_new) {
2721 // Make sure the function is the Array() function 2867 // Make sure the function is the Array() function.
2722 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); 2868 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7);
2723 __ cmp(r1, r4); 2869 __ cmp(r4, r7);
2724 __ b(ne, &not_array_function); 2870 __ bne(&not_array_function);
2725 2871
2726 // The target function is the Array constructor, 2872 // The target function is the Array constructor,
2727 // Create an AllocationSite if we don't already have it, store it in the 2873 // Create an AllocationSite if we don't already have it, store it in the
2728 // slot. 2874 // slot.
2729 { 2875 {
2730 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2876 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
2731 2877
2732 // Arguments register must be smi-tagged to call out. 2878 // Arguments register must be smi-tagged to call out.
2733 __ SmiTag(r0); 2879 __ SmiTag(r3);
2734 __ Push(r3, r2, r1, r0); 2880 __ Push(r6, r5, r4, r3);
2735 2881
2736 CreateAllocationSiteStub create_stub(masm->isolate()); 2882 CreateAllocationSiteStub create_stub(masm->isolate());
2737 __ CallStub(&create_stub); 2883 __ CallStub(&create_stub);
2738 2884
2739 __ Pop(r3, r2, r1, r0); 2885 __ Pop(r6, r5, r4, r3);
2740 __ SmiUntag(r0); 2886 __ SmiUntag(r3);
2741 } 2887 }
2742 __ b(&done); 2888 __ b(&done);
2743 2889
2744 __ bind(&not_array_function); 2890 __ bind(&not_array_function);
2745 } 2891 }
2746 2892
2747 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); 2893 __ SmiToPtrArrayOffset(r7, r6);
2748 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 2894 __ add(r7, r5, r7);
2749 __ str(r1, MemOperand(r4, 0)); 2895 __ addi(r7, r7, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
2896 __ StoreP(r4, MemOperand(r7, 0));
2750 2897
2751 __ Push(r4, r2, r1); 2898 __ Push(r7, r5, r4);
2752 __ RecordWrite(r2, r4, r1, kLRHasNotBeenSaved, kDontSaveFPRegs, 2899 __ RecordWrite(r5, r7, r4, kLRHasNotBeenSaved, kDontSaveFPRegs,
2753 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 2900 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
2754 __ Pop(r4, r2, r1); 2901 __ Pop(r7, r5, r4);
2755 2902
2756 __ bind(&done); 2903 __ bind(&done);
2757 } 2904 }
2758 2905
2759 2906
2760 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { 2907 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) {
2761 // Do not transform the receiver for strict mode functions. 2908 // Do not transform the receiver for strict mode functions and natives.
2762 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 2909 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
2763 __ ldr(r4, FieldMemOperand(r3, SharedFunctionInfo::kCompilerHintsOffset)); 2910 __ lwz(r7, FieldMemOperand(r6, SharedFunctionInfo::kCompilerHintsOffset));
2764 __ tst(r4, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 2911 __ TestBit(r7,
2765 kSmiTagSize))); 2912 #if V8_TARGET_ARCH_PPC64
2766 __ b(ne, cont); 2913 SharedFunctionInfo::kStrictModeFunction,
2914 #else
2915 SharedFunctionInfo::kStrictModeFunction + kSmiTagSize,
2916 #endif
2917 r0);
2918 __ bne(cont, cr0);
2767 2919
2768 // Do not transform the receiver for native (Compilerhints already in r3). 2920 // Do not transform the receiver for native.
2769 __ tst(r4, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 2921 __ TestBit(r7,
2770 __ b(ne, cont); 2922 #if V8_TARGET_ARCH_PPC64
2923 SharedFunctionInfo::kNative,
2924 #else
2925 SharedFunctionInfo::kNative + kSmiTagSize,
2926 #endif
2927 r0);
2928 __ bne(cont, cr0);
2771 } 2929 }
2772 2930
2773 2931
2774 static void EmitSlowCase(MacroAssembler* masm, 2932 static void EmitSlowCase(MacroAssembler* masm,
2775 int argc, 2933 int argc,
2776 Label* non_function) { 2934 Label* non_function) {
2777 // Check for function proxy. 2935 // Check for function proxy.
2778 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); 2936 STATIC_ASSERT(JS_FUNCTION_PROXY_TYPE < 0xffffu);
2779 __ b(ne, non_function); 2937 __ cmpi(r7, Operand(JS_FUNCTION_PROXY_TYPE));
2780 __ push(r1); // put proxy as additional argument 2938 __ bne(non_function);
2781 __ mov(r0, Operand(argc + 1, RelocInfo::NONE32)); 2939 __ push(r4); // put proxy as additional argument
2782 __ mov(r2, Operand::Zero()); 2940 __ li(r3, Operand(argc + 1));
2783 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY); 2941 __ li(r5, Operand::Zero());
2942 __ GetBuiltinFunction(r4, Builtins::CALL_FUNCTION_PROXY);
2784 { 2943 {
2785 Handle<Code> adaptor = 2944 Handle<Code> adaptor =
2786 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); 2945 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
2787 __ Jump(adaptor, RelocInfo::CODE_TARGET); 2946 __ Jump(adaptor, RelocInfo::CODE_TARGET);
2788 } 2947 }
2789 2948
2790 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 2949 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
2791 // of the original receiver from the call site). 2950 // of the original receiver from the call site).
2792 __ bind(non_function); 2951 __ bind(non_function);
2793 __ str(r1, MemOperand(sp, argc * kPointerSize)); 2952 __ StoreP(r4, MemOperand(sp, argc * kPointerSize), r0);
2794 __ mov(r0, Operand(argc)); // Set up the number of arguments. 2953 __ li(r3, Operand(argc)); // Set up the number of arguments.
2795 __ mov(r2, Operand::Zero()); 2954 __ li(r5, Operand::Zero());
2796 __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION); 2955 __ GetBuiltinFunction(r4, Builtins::CALL_NON_FUNCTION);
2797 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 2956 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
2798 RelocInfo::CODE_TARGET); 2957 RelocInfo::CODE_TARGET);
2799 } 2958 }
2800 2959
2801 2960
2802 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { 2961 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
2803 // Wrap the receiver and patch it back onto the stack. 2962 // Wrap the receiver and patch it back onto the stack.
2804 { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); 2963 { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
2805 __ Push(r1, r3); 2964 __ Push(r4, r6);
2806 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 2965 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
2807 __ pop(r1); 2966 __ pop(r4);
2808 } 2967 }
2809 __ str(r0, MemOperand(sp, argc * kPointerSize)); 2968 __ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0);
2810 __ jmp(cont); 2969 __ b(cont);
2811 } 2970 }
2812 2971
2813 2972
2814 static void CallFunctionNoFeedback(MacroAssembler* masm, 2973 static void CallFunctionNoFeedback(MacroAssembler* masm,
2815 int argc, bool needs_checks, 2974 int argc, bool needs_checks,
2816 bool call_as_method) { 2975 bool call_as_method) {
2817 // r1 : the function to call 2976 // r4 : the function to call
2818 Label slow, non_function, wrap, cont; 2977 Label slow, non_function, wrap, cont;
2819 2978
2820 if (needs_checks) { 2979 if (needs_checks) {
2821 // Check that the function is really a JavaScript function. 2980 // Check that the function is really a JavaScript function.
2822 // r1: pushed function (to be verified) 2981 // r4: pushed function (to be verified)
2823 __ JumpIfSmi(r1, &non_function); 2982 __ JumpIfSmi(r4, &non_function);
2824 2983
2825 // Goto slow case if we do not have a function. 2984 // Goto slow case if we do not have a function.
2826 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); 2985 __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE);
2827 __ b(ne, &slow); 2986 __ bne(&slow);
2828 } 2987 }
2829 2988
2830 // Fast-case: Invoke the function now. 2989 // Fast-case: Invoke the function now.
2831 // r1: pushed function 2990 // r4: pushed function
2832 ParameterCount actual(argc); 2991 ParameterCount actual(argc);
2833 2992
2834 if (call_as_method) { 2993 if (call_as_method) {
2835 if (needs_checks) { 2994 if (needs_checks) {
2836 EmitContinueIfStrictOrNative(masm, &cont); 2995 EmitContinueIfStrictOrNative(masm, &cont);
2837 } 2996 }
2838 2997
2839 // Compute the receiver in sloppy mode. 2998 // Compute the receiver in sloppy mode.
2840 __ ldr(r3, MemOperand(sp, argc * kPointerSize)); 2999 __ LoadP(r6, MemOperand(sp, argc * kPointerSize), r0);
2841 3000
2842 if (needs_checks) { 3001 if (needs_checks) {
2843 __ JumpIfSmi(r3, &wrap); 3002 __ JumpIfSmi(r6, &wrap);
2844 __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE); 3003 __ CompareObjectType(r6, r7, r7, FIRST_SPEC_OBJECT_TYPE);
2845 __ b(lt, &wrap); 3004 __ blt(&wrap);
2846 } else { 3005 } else {
2847 __ jmp(&wrap); 3006 __ b(&wrap);
2848 } 3007 }
2849 3008
2850 __ bind(&cont); 3009 __ bind(&cont);
2851 } 3010 }
2852 3011
2853 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); 3012 __ InvokeFunction(r4, actual, JUMP_FUNCTION, NullCallWrapper());
2854 3013
2855 if (needs_checks) { 3014 if (needs_checks) {
2856 // Slow-case: Non-function called. 3015 // Slow-case: Non-function called.
2857 __ bind(&slow); 3016 __ bind(&slow);
2858 EmitSlowCase(masm, argc, &non_function); 3017 EmitSlowCase(masm, argc, &non_function);
2859 } 3018 }
2860 3019
2861 if (call_as_method) { 3020 if (call_as_method) {
2862 __ bind(&wrap); 3021 __ bind(&wrap);
2863 EmitWrapCase(masm, argc, &cont); 3022 EmitWrapCase(masm, argc, &cont);
2864 } 3023 }
2865 } 3024 }
2866 3025
2867 3026
2868 void CallFunctionStub::Generate(MacroAssembler* masm) { 3027 void CallFunctionStub::Generate(MacroAssembler* masm) {
2869 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); 3028 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod());
2870 } 3029 }
2871 3030
2872 3031
2873 void CallConstructStub::Generate(MacroAssembler* masm) { 3032 void CallConstructStub::Generate(MacroAssembler* masm) {
2874 // r0 : number of arguments 3033 // r3 : number of arguments
2875 // r1 : the function to call 3034 // r4 : the function to call
2876 // r2 : feedback vector 3035 // r5 : feedback vector
2877 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback 3036 // r6 : (only if r5 is not the megamorphic symbol) slot in feedback
2878 // vector (Smi) 3037 // vector (Smi)
2879 Label slow, non_function_call; 3038 Label slow, non_function_call;
2880 3039
2881 // Check that the function is not a smi. 3040 // Check that the function is not a smi.
2882 __ JumpIfSmi(r1, &non_function_call); 3041 __ JumpIfSmi(r4, &non_function_call);
2883 // Check that the function is a JSFunction. 3042 // Check that the function is a JSFunction.
2884 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); 3043 __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE);
2885 __ b(ne, &slow); 3044 __ bne(&slow);
2886 3045
2887 if (RecordCallTarget()) { 3046 if (RecordCallTarget()) {
2888 GenerateRecordCallTarget(masm); 3047 GenerateRecordCallTarget(masm);
2889 3048
2890 __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3)); 3049 __ SmiToPtrArrayOffset(r8, r6);
3050 __ add(r8, r5, r8);
2891 if (FLAG_pretenuring_call_new) { 3051 if (FLAG_pretenuring_call_new) {
2892 // Put the AllocationSite from the feedback vector into r2. 3052 // Put the AllocationSite from the feedback vector into r5.
2893 // By adding kPointerSize we encode that we know the AllocationSite 3053 // By adding kPointerSize we encode that we know the AllocationSite
2894 // entry is at the feedback vector slot given by r3 + 1. 3054 // entry is at the feedback vector slot given by r6 + 1.
2895 __ ldr(r2, FieldMemOperand(r5, FixedArray::kHeaderSize + kPointerSize)); 3055 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize + kPointerSize));
2896 } else { 3056 } else {
2897 Label feedback_register_initialized; 3057 Label feedback_register_initialized;
2898 // Put the AllocationSite from the feedback vector into r2, or undefined. 3058 // Put the AllocationSite from the feedback vector into r5, or undefined.
2899 __ ldr(r2, FieldMemOperand(r5, FixedArray::kHeaderSize)); 3059 __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize));
2900 __ ldr(r5, FieldMemOperand(r2, AllocationSite::kMapOffset)); 3060 __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset));
2901 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); 3061 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
2902 __ b(eq, &feedback_register_initialized); 3062 __ beq(&feedback_register_initialized);
2903 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 3063 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
2904 __ bind(&feedback_register_initialized); 3064 __ bind(&feedback_register_initialized);
2905 } 3065 }
2906 3066
2907 __ AssertUndefinedOrAllocationSite(r2, r5); 3067 __ AssertUndefinedOrAllocationSite(r5, r8);
2908 } 3068 }
2909 3069
2910 // Jump to the function-specific construct stub. 3070 // Jump to the function-specific construct stub.
2911 Register jmp_reg = r4; 3071 Register jmp_reg = r7;
2912 __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 3072 __ LoadP(jmp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
2913 __ ldr(jmp_reg, FieldMemOperand(jmp_reg, 3073 __ LoadP(jmp_reg, FieldMemOperand(jmp_reg,
2914 SharedFunctionInfo::kConstructStubOffset)); 3074 SharedFunctionInfo::kConstructStubOffset));
2915 __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); 3075 __ addi(r0, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
3076 __ Jump(r0);
2916 3077
2917 // r0: number of arguments 3078 // r3: number of arguments
2918 // r1: called object 3079 // r4: called object
2919 // r4: object type 3080 // r7: object type
2920 Label do_call; 3081 Label do_call;
2921 __ bind(&slow); 3082 __ bind(&slow);
2922 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); 3083 STATIC_ASSERT(JS_FUNCTION_PROXY_TYPE < 0xffffu);
2923 __ b(ne, &non_function_call); 3084 __ cmpi(r7, Operand(JS_FUNCTION_PROXY_TYPE));
2924 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); 3085 __ bne(&non_function_call);
2925 __ jmp(&do_call); 3086 __ GetBuiltinFunction(r4, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
3087 __ b(&do_call);
2926 3088
2927 __ bind(&non_function_call); 3089 __ bind(&non_function_call);
2928 __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); 3090 __ GetBuiltinFunction(r4, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
2929 __ bind(&do_call); 3091 __ bind(&do_call);
2930 // Set expected number of arguments to zero (not changing r0). 3092 // Set expected number of arguments to zero (not changing r3).
2931 __ mov(r2, Operand::Zero()); 3093 __ li(r5, Operand::Zero());
2932 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 3094 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
2933 RelocInfo::CODE_TARGET); 3095 RelocInfo::CODE_TARGET);
2934 } 3096 }
2935 3097
2936 3098
2937 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { 3099 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
2938 __ ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 3100 __ LoadP(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2939 __ ldr(vector, FieldMemOperand(vector, 3101 __ LoadP(vector, FieldMemOperand(vector,
2940 JSFunction::kSharedFunctionInfoOffset)); 3102 JSFunction::kSharedFunctionInfoOffset));
2941 __ ldr(vector, FieldMemOperand(vector, 3103 __ LoadP(vector, FieldMemOperand(vector,
2942 SharedFunctionInfo::kFeedbackVectorOffset)); 3104 SharedFunctionInfo::kFeedbackVectorOffset));
2943 } 3105 }
2944 3106
2945 3107
2946 void CallIC_ArrayStub::Generate(MacroAssembler* masm) { 3108 void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
2947 // r1 - function 3109 // r4 - function
2948 // r3 - slot id 3110 // r6 - slot id
2949 Label miss; 3111 Label miss;
2950 int argc = state_.arg_count(); 3112 int argc = state_.arg_count();
2951 ParameterCount actual(argc); 3113 ParameterCount actual(argc);
2952 3114
2953 EmitLoadTypeFeedbackVector(masm, r2); 3115 EmitLoadTypeFeedbackVector(masm, r5);
2954 3116
2955 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); 3117 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7);
2956 __ cmp(r1, r4); 3118 __ cmp(r4, r7);
2957 __ b(ne, &miss); 3119 __ bne(&miss);
2958 3120
2959 __ mov(r0, Operand(arg_count())); 3121 __ mov(r3, Operand(arg_count()));
2960 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); 3122 __ SmiToPtrArrayOffset(r7, r6);
2961 __ ldr(r2, FieldMemOperand(r4, FixedArray::kHeaderSize)); 3123 __ add(r7, r5, r7);
2962 // Verify that r2 contains an AllocationSite 3124 __ LoadP(r5, FieldMemOperand(r7, FixedArray::kHeaderSize));
2963 __ AssertUndefinedOrAllocationSite(r2, r4); 3125 // Verify that r5 contains an AllocationSite
3126 __ AssertUndefinedOrAllocationSite(r5, r7);
2964 ArrayConstructorStub stub(masm->isolate(), arg_count()); 3127 ArrayConstructorStub stub(masm->isolate(), arg_count());
2965 __ TailCallStub(&stub); 3128 __ TailCallStub(&stub);
2966 3129
2967 __ bind(&miss); 3130 __ bind(&miss);
2968 GenerateMiss(masm, IC::kCallIC_Customization_Miss); 3131 GenerateMiss(masm, IC::kCallIC_Customization_Miss);
2969 3132
2970 // The slow case, we need this no matter what to complete a call after a miss. 3133 // The slow case, we need this no matter what to complete a call after a miss.
2971 CallFunctionNoFeedback(masm, 3134 CallFunctionNoFeedback(masm,
2972 arg_count(), 3135 arg_count(),
2973 true, 3136 true,
2974 CallAsMethod()); 3137 CallAsMethod());
2975 3138
2976 // Unreachable. 3139 // Unreachable.
2977 __ stop("Unexpected code address"); 3140 __ stop("Unexpected code address");
2978 } 3141 }
2979 3142
2980 3143
2981 void CallICStub::Generate(MacroAssembler* masm) { 3144 void CallICStub::Generate(MacroAssembler* masm) {
2982 // r1 - function 3145 // r4 - function
2983 // r3 - slot id (Smi) 3146 // r6 - slot id (Smi)
2984 Label extra_checks_or_miss, slow_start; 3147 Label extra_checks_or_miss, slow_start;
2985 Label slow, non_function, wrap, cont; 3148 Label slow, non_function, wrap, cont;
2986 Label have_js_function; 3149 Label have_js_function;
2987 int argc = state_.arg_count(); 3150 int argc = state_.arg_count();
2988 ParameterCount actual(argc); 3151 ParameterCount actual(argc);
2989 3152
2990 EmitLoadTypeFeedbackVector(masm, r2); 3153 EmitLoadTypeFeedbackVector(masm, r5);
2991 3154
2992 // The checks. First, does r1 match the recorded monomorphic target? 3155 // The checks. First, does r4 match the recorded monomorphic target?
2993 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); 3156 __ SmiToPtrArrayOffset(r7, r6);
2994 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); 3157 __ add(r7, r5, r7);
2995 __ cmp(r1, r4); 3158 __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize));
2996 __ b(ne, &extra_checks_or_miss); 3159 __ cmp(r4, r7);
3160 __ bne(&extra_checks_or_miss);
2997 3161
2998 __ bind(&have_js_function); 3162 __ bind(&have_js_function);
2999 if (state_.CallAsMethod()) { 3163 if (state_.CallAsMethod()) {
3000 EmitContinueIfStrictOrNative(masm, &cont); 3164 EmitContinueIfStrictOrNative(masm, &cont);
3001 // Compute the receiver in sloppy mode. 3165 // Compute the receiver in sloppy mode.
3002 __ ldr(r3, MemOperand(sp, argc * kPointerSize)); 3166 __ LoadP(r6, MemOperand(sp, argc * kPointerSize), r0);
3003 3167
3004 __ JumpIfSmi(r3, &wrap); 3168 __ JumpIfSmi(r6, &wrap);
3005 __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE); 3169 __ CompareObjectType(r6, r7, r7, FIRST_SPEC_OBJECT_TYPE);
3006 __ b(lt, &wrap); 3170 __ blt(&wrap);
3007 3171
3008 __ bind(&cont); 3172 __ bind(&cont);
3009 } 3173 }
3010 3174
3011 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); 3175 __ InvokeFunction(r4, actual, JUMP_FUNCTION, NullCallWrapper());
3012 3176
3013 __ bind(&slow); 3177 __ bind(&slow);
3014 EmitSlowCase(masm, argc, &non_function); 3178 EmitSlowCase(masm, argc, &non_function);
3015 3179
3016 if (state_.CallAsMethod()) { 3180 if (state_.CallAsMethod()) {
3017 __ bind(&wrap); 3181 __ bind(&wrap);
3018 EmitWrapCase(masm, argc, &cont); 3182 EmitWrapCase(masm, argc, &cont);
3019 } 3183 }
3020 3184
3021 __ bind(&extra_checks_or_miss); 3185 __ bind(&extra_checks_or_miss);
3022 Label miss; 3186 Label miss;
3023 3187
3024 __ CompareRoot(r4, Heap::kMegamorphicSymbolRootIndex); 3188 __ CompareRoot(r7, Heap::kMegamorphicSymbolRootIndex);
3025 __ b(eq, &slow_start); 3189 __ beq(&slow_start);
3026 __ CompareRoot(r4, Heap::kUninitializedSymbolRootIndex); 3190 __ CompareRoot(r7, Heap::kUninitializedSymbolRootIndex);
3027 __ b(eq, &miss); 3191 __ beq(&miss);
3028 3192
3029 if (!FLAG_trace_ic) { 3193 if (!FLAG_trace_ic) {
3030 // We are going megamorphic, and we don't want to visit the runtime. 3194 // We are going megamorphic, and we don't want to visit the runtime.
3031 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); 3195 __ SmiToPtrArrayOffset(r7, r6);
3196 __ add(r7, r5, r7);
3032 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex); 3197 __ LoadRoot(ip, Heap::kMegamorphicSymbolRootIndex);
3033 __ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize)); 3198 __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0);
3034 __ jmp(&slow_start); 3199 __ jmp(&slow_start);
3035 } 3200 }
3036 3201
3037 // We are here because tracing is on or we are going monomorphic. 3202 // We are here because tracing is on or we are going monomorphic.
3038 __ bind(&miss); 3203 __ bind(&miss);
3039 GenerateMiss(masm, IC::kCallIC_Miss); 3204 GenerateMiss(masm, IC::kCallIC_Miss);
3040 3205
3041 // the slow case 3206 // the slow case
3042 __ bind(&slow_start); 3207 __ bind(&slow_start);
3043 // Check that the function is really a JavaScript function. 3208 // Check that the function is really a JavaScript function.
3044 // r1: pushed function (to be verified) 3209 // r4: pushed function (to be verified)
3045 __ JumpIfSmi(r1, &non_function); 3210 __ JumpIfSmi(r4, &non_function);
3046 3211
3047 // Goto slow case if we do not have a function. 3212 // Goto slow case if we do not have a function.
3048 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); 3213 __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE);
3049 __ b(ne, &slow); 3214 __ bne(&slow);
3050 __ jmp(&have_js_function); 3215 __ b(&have_js_function);
3051 } 3216 }
3052 3217
3053 3218
3054 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { 3219 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) {
3055 // Get the receiver of the function from the stack; 1 ~ return address. 3220 // Get the receiver of the function from the stack; 1 ~ return address.
3056 __ ldr(r4, MemOperand(sp, (state_.arg_count() + 1) * kPointerSize)); 3221 __ LoadP(r7, MemOperand(sp, (state_.arg_count() + 1) * kPointerSize), r0);
3057 3222
3058 { 3223 {
3059 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 3224 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
3060 3225
3061 // Push the receiver and the function and feedback info. 3226 // Push the receiver and the function and feedback info.
3062 __ Push(r4, r1, r2, r3); 3227 __ Push(r7, r4, r5, r6);
3063 3228
3064 // Call the entry. 3229 // Call the entry.
3065 ExternalReference miss = ExternalReference(IC_Utility(id), 3230 ExternalReference miss = ExternalReference(IC_Utility(id),
3066 masm->isolate()); 3231 masm->isolate());
3067 __ CallExternalReference(miss, 4); 3232 __ CallExternalReference(miss, 4);
3068 3233
3069 // Move result to edi and exit the internal frame. 3234 // Move result to r4 and exit the internal frame.
3070 __ mov(r1, r0); 3235 __ mr(r4, r3);
3071 } 3236 }
3072 } 3237 }
3073 3238
3074 3239
3075 // StringCharCodeAtGenerator 3240 // StringCharCodeAtGenerator
3076 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 3241 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
3077 Label flat_string; 3242 Label flat_string;
3078 Label ascii_string; 3243 Label ascii_string;
3079 Label got_char_code; 3244 Label got_char_code;
3080 Label sliced_string; 3245 Label sliced_string;
3081 3246
3082 // If the receiver is a smi trigger the non-string case. 3247 // If the receiver is a smi trigger the non-string case.
3083 __ JumpIfSmi(object_, receiver_not_string_); 3248 __ JumpIfSmi(object_, receiver_not_string_);
3084 3249
3085 // Fetch the instance type of the receiver into result register. 3250 // Fetch the instance type of the receiver into result register.
3086 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 3251 __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
3087 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 3252 __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
3088 // If the receiver is not a string trigger the non-string case. 3253 // If the receiver is not a string trigger the non-string case.
3089 __ tst(result_, Operand(kIsNotStringMask)); 3254 __ andi(r0, result_, Operand(kIsNotStringMask));
3090 __ b(ne, receiver_not_string_); 3255 __ bne(receiver_not_string_, cr0);
3091 3256
3092 // If the index is non-smi trigger the non-smi case. 3257 // If the index is non-smi trigger the non-smi case.
3093 __ JumpIfNotSmi(index_, &index_not_smi_); 3258 __ JumpIfNotSmi(index_, &index_not_smi_);
3094 __ bind(&got_smi_index_); 3259 __ bind(&got_smi_index_);
3095 3260
3096 // Check for index out of range. 3261 // Check for index out of range.
3097 __ ldr(ip, FieldMemOperand(object_, String::kLengthOffset)); 3262 __ LoadP(ip, FieldMemOperand(object_, String::kLengthOffset));
3098 __ cmp(ip, Operand(index_)); 3263 __ cmpl(ip, index_);
3099 __ b(ls, index_out_of_range_); 3264 __ ble(index_out_of_range_);
3100 3265
3101 __ SmiUntag(index_); 3266 __ SmiUntag(index_);
3102 3267
3103 StringCharLoadGenerator::Generate(masm, 3268 StringCharLoadGenerator::Generate(masm,
3104 object_, 3269 object_,
3105 index_, 3270 index_,
3106 result_, 3271 result_,
3107 &call_runtime_); 3272 &call_runtime_);
3108 3273
3109 __ SmiTag(result_); 3274 __ SmiTag(result_);
(...skipping 19 matching lines...) Expand all
3129 __ push(index_); // Consumed by runtime conversion function. 3294 __ push(index_); // Consumed by runtime conversion function.
3130 if (index_flags_ == STRING_INDEX_IS_NUMBER) { 3295 if (index_flags_ == STRING_INDEX_IS_NUMBER) {
3131 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 3296 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
3132 } else { 3297 } else {
3133 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 3298 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
3134 // NumberToSmi discards numbers that are not exact integers. 3299 // NumberToSmi discards numbers that are not exact integers.
3135 __ CallRuntime(Runtime::kNumberToSmi, 1); 3300 __ CallRuntime(Runtime::kNumberToSmi, 1);
3136 } 3301 }
3137 // Save the conversion result before the pop instructions below 3302 // Save the conversion result before the pop instructions below
3138 // have a chance to overwrite it. 3303 // have a chance to overwrite it.
3139 __ Move(index_, r0); 3304 __ Move(index_, r3);
3140 __ pop(object_); 3305 __ pop(object_);
3141 // Reload the instance type. 3306 // Reload the instance type.
3142 __ ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 3307 __ LoadP(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
3143 __ ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 3308 __ lbz(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
3144 call_helper.AfterCall(masm); 3309 call_helper.AfterCall(masm);
3145 // If index is still not a smi, it must be out of range. 3310 // If index is still not a smi, it must be out of range.
3146 __ JumpIfNotSmi(index_, index_out_of_range_); 3311 __ JumpIfNotSmi(index_, index_out_of_range_);
3147 // Otherwise, return to the fast path. 3312 // Otherwise, return to the fast path.
3148 __ jmp(&got_smi_index_); 3313 __ b(&got_smi_index_);
3149 3314
3150 // Call runtime. We get here when the receiver is a string and the 3315 // Call runtime. We get here when the receiver is a string and the
3151 // index is a number, but the code of getting the actual character 3316 // index is a number, but the code of getting the actual character
3152 // is too complex (e.g., when the string needs to be flattened). 3317 // is too complex (e.g., when the string needs to be flattened).
3153 __ bind(&call_runtime_); 3318 __ bind(&call_runtime_);
3154 call_helper.BeforeCall(masm); 3319 call_helper.BeforeCall(masm);
3155 __ SmiTag(index_); 3320 __ SmiTag(index_);
3156 __ Push(object_, index_); 3321 __ Push(object_, index_);
3157 __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); 3322 __ CallRuntime(Runtime::kStringCharCodeAtRT, 2);
3158 __ Move(result_, r0); 3323 __ Move(result_, r3);
3159 call_helper.AfterCall(masm); 3324 call_helper.AfterCall(masm);
3160 __ jmp(&exit_); 3325 __ b(&exit_);
3161 3326
3162 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); 3327 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
3163 } 3328 }
3164 3329
3165 3330
3166 // ------------------------------------------------------------------------- 3331 // -------------------------------------------------------------------------
3167 // StringCharFromCodeGenerator 3332 // StringCharFromCodeGenerator
3168 3333
3169 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 3334 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
3170 // Fast case of Heap::LookupSingleCharacterStringFromCode. 3335 // Fast case of Heap::LookupSingleCharacterStringFromCode.
3171 STATIC_ASSERT(kSmiTag == 0);
3172 STATIC_ASSERT(kSmiShiftSize == 0);
3173 ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1)); 3336 ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1));
3174 __ tst(code_, 3337 __ LoadSmiLiteral(r0, Smi::FromInt(~String::kMaxOneByteCharCode));
3175 Operand(kSmiTagMask | 3338 __ ori(r0, r0, Operand(kSmiTagMask));
3176 ((~String::kMaxOneByteCharCode) << kSmiTagSize))); 3339 __ and_(r0, code_, r0);
3177 __ b(ne, &slow_case_); 3340 __ cmpi(r0, Operand::Zero());
3341 __ bne(&slow_case_);
3178 3342
3179 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); 3343 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
3180 // At this point code register contains smi tagged ASCII char code. 3344 // At this point code register contains smi tagged ASCII char code.
3181 __ add(result_, result_, Operand::PointerOffsetFromSmiKey(code_)); 3345 __ mr(r0, code_);
3182 __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); 3346 __ SmiToPtrArrayOffset(code_, code_);
3347 __ add(result_, result_, code_);
3348 __ mr(code_, r0);
3349 __ LoadP(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
3183 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex); 3350 __ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
3184 __ b(eq, &slow_case_); 3351 __ beq(&slow_case_);
3185 __ bind(&exit_); 3352 __ bind(&exit_);
3186 } 3353 }
3187 3354
3188 3355
3189 void StringCharFromCodeGenerator::GenerateSlow( 3356 void StringCharFromCodeGenerator::GenerateSlow(
3190 MacroAssembler* masm, 3357 MacroAssembler* masm,
3191 const RuntimeCallHelper& call_helper) { 3358 const RuntimeCallHelper& call_helper) {
3192 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); 3359 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
3193 3360
3194 __ bind(&slow_case_); 3361 __ bind(&slow_case_);
3195 call_helper.BeforeCall(masm); 3362 call_helper.BeforeCall(masm);
3196 __ push(code_); 3363 __ push(code_);
3197 __ CallRuntime(Runtime::kCharFromCode, 1); 3364 __ CallRuntime(Runtime::kCharFromCode, 1);
3198 __ Move(result_, r0); 3365 __ Move(result_, r3);
3199 call_helper.AfterCall(masm); 3366 call_helper.AfterCall(masm);
3200 __ jmp(&exit_); 3367 __ b(&exit_);
3201 3368
3202 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); 3369 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
3203 } 3370 }
3204 3371
3205 3372
3206 enum CopyCharactersFlags { 3373 enum CopyCharactersFlags {
3207 COPY_ASCII = 1, 3374 COPY_ASCII = 1,
3208 DEST_ALWAYS_ALIGNED = 2 3375 DEST_ALWAYS_ALIGNED = 2
3209 }; 3376 };
3210 3377
3211 3378
3212 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, 3379 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm,
3213 Register dest, 3380 Register dest,
3214 Register src, 3381 Register src,
3215 Register count, 3382 Register count,
3216 Register scratch, 3383 Register scratch,
3217 String::Encoding encoding) { 3384 String::Encoding encoding) {
3218 if (FLAG_debug_code) { 3385 if (FLAG_debug_code) {
3219 // Check that destination is word aligned. 3386 // Check that destination is word aligned.
3220 __ tst(dest, Operand(kPointerAlignmentMask)); 3387 __ andi(r0, dest, Operand(kPointerAlignmentMask));
3221 __ Check(eq, kDestinationOfCopyNotAligned); 3388 __ Check(eq, kDestinationOfCopyNotAligned, cr0);
3222 } 3389 }
3223 3390
3224 // Assumes word reads and writes are little endian.
3225 // Nothing to do for zero characters. 3391 // Nothing to do for zero characters.
3226 Label done; 3392 Label done;
3227 if (encoding == String::TWO_BYTE_ENCODING) { 3393 if (encoding == String::TWO_BYTE_ENCODING) {
3228 __ add(count, count, Operand(count), SetCC); 3394 // double the length
3395 __ add(count, count, count, LeaveOE, SetRC);
3396 __ beq(&done, cr0);
3397 } else {
3398 __ cmpi(count, Operand::Zero());
3399 __ beq(&done);
3229 } 3400 }
3230 3401
3231 Register limit = count; // Read until dest equals this. 3402 // Copy count bytes from src to dst.
3232 __ add(limit, dest, Operand(count)); 3403 Label byte_loop;
3233 3404 __ mtctr(count);
3234 Label loop_entry, loop; 3405 __ bind(&byte_loop);
3235 // Copy bytes from src to dest until dest hits limit. 3406 __ lbz(scratch, MemOperand(src));
3236 __ b(&loop_entry); 3407 __ addi(src, src, Operand(1));
3237 __ bind(&loop); 3408 __ stb(scratch, MemOperand(dest));
3238 __ ldrb(scratch, MemOperand(src, 1, PostIndex), lt); 3409 __ addi(dest, dest, Operand(1));
3239 __ strb(scratch, MemOperand(dest, 1, PostIndex)); 3410 __ bdnz(&byte_loop);
3240 __ bind(&loop_entry);
3241 __ cmp(dest, Operand(limit));
3242 __ b(lt, &loop);
3243 3411
3244 __ bind(&done); 3412 __ bind(&done);
3245 } 3413 }
3246 3414
3247 3415
3248 void StringHelper::GenerateHashInit(MacroAssembler* masm, 3416 void StringHelper::GenerateHashInit(MacroAssembler* masm,
3249 Register hash, 3417 Register hash,
3250 Register character) { 3418 Register character,
3419 Register scratch) {
3251 // hash = character + (character << 10); 3420 // hash = character + (character << 10);
3252 __ LoadRoot(hash, Heap::kHashSeedRootIndex); 3421 __ LoadRoot(hash, Heap::kHashSeedRootIndex);
3253 // Untag smi seed and add the character. 3422 // Untag smi seed and add the character.
3254 __ add(hash, character, Operand(hash, LSR, kSmiTagSize)); 3423 __ SmiUntag(scratch, hash);
3424 __ add(hash, character, scratch);
3255 // hash += hash << 10; 3425 // hash += hash << 10;
3256 __ add(hash, hash, Operand(hash, LSL, 10)); 3426 __ slwi(scratch, hash, Operand(10));
3427 __ add(hash, hash, scratch);
3257 // hash ^= hash >> 6; 3428 // hash ^= hash >> 6;
3258 __ eor(hash, hash, Operand(hash, LSR, 6)); 3429 __ srwi(scratch, hash, Operand(6));
3430 __ xor_(hash, hash, scratch);
3259 } 3431 }
3260 3432
3261 3433
3262 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, 3434 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
3263 Register hash, 3435 Register hash,
3264 Register character) { 3436 Register character,
3437 Register scratch) {
3265 // hash += character; 3438 // hash += character;
3266 __ add(hash, hash, Operand(character)); 3439 __ add(hash, hash, character);
3267 // hash += hash << 10; 3440 // hash += hash << 10;
3268 __ add(hash, hash, Operand(hash, LSL, 10)); 3441 __ slwi(scratch, hash, Operand(10));
3442 __ add(hash, hash, scratch);
3269 // hash ^= hash >> 6; 3443 // hash ^= hash >> 6;
3270 __ eor(hash, hash, Operand(hash, LSR, 6)); 3444 __ srwi(scratch, hash, Operand(6));
3445 __ xor_(hash, hash, scratch);
3271 } 3446 }
3272 3447
3273 3448
3274 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, 3449 void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
3275 Register hash) { 3450 Register hash,
3451 Register scratch) {
3276 // hash += hash << 3; 3452 // hash += hash << 3;
3277 __ add(hash, hash, Operand(hash, LSL, 3)); 3453 __ slwi(scratch, hash, Operand(3));
3454 __ add(hash, hash, scratch);
3278 // hash ^= hash >> 11; 3455 // hash ^= hash >> 11;
3279 __ eor(hash, hash, Operand(hash, LSR, 11)); 3456 __ srwi(scratch, hash, Operand(11));
3457 __ xor_(hash, hash, scratch);
3280 // hash += hash << 15; 3458 // hash += hash << 15;
3281 __ add(hash, hash, Operand(hash, LSL, 15)); 3459 __ slwi(scratch, hash, Operand(15));
3460 __ add(hash, hash, scratch);
3282 3461
3283 __ and_(hash, hash, Operand(String::kHashBitMask), SetCC); 3462 __ mov(scratch, Operand(String::kHashBitMask));
3463 __ and_(hash, hash, scratch, SetRC);
3284 3464
3285 // if (hash == 0) hash = 27; 3465 // if (hash == 0) hash = 27;
3286 __ mov(hash, Operand(StringHasher::kZeroHash), LeaveCC, eq); 3466 Label done;
3467 __ bne(&done, cr0);
3468 __ li(hash, Operand(StringHasher::kZeroHash));
3469 __ bind(&done);
3287 } 3470 }
3288 3471
3289 3472
3290 void SubStringStub::Generate(MacroAssembler* masm) { 3473 void SubStringStub::Generate(MacroAssembler* masm) {
3291 Label runtime; 3474 Label runtime;
3292 3475
3293 // Stack frame on entry. 3476 // Stack frame on entry.
3294 // lr: return address 3477 // lr: return address
3295 // sp[0]: to 3478 // sp[0]: to
3296 // sp[4]: from 3479 // sp[4]: from
3297 // sp[8]: string 3480 // sp[8]: string
3298 3481
3299 // This stub is called from the native-call %_SubString(...), so 3482 // This stub is called from the native-call %_SubString(...), so
3300 // nothing can be assumed about the arguments. It is tested that: 3483 // nothing can be assumed about the arguments. It is tested that:
3301 // "string" is a sequential string, 3484 // "string" is a sequential string,
3302 // both "from" and "to" are smis, and 3485 // both "from" and "to" are smis, and
3303 // 0 <= from <= to <= string.length. 3486 // 0 <= from <= to <= string.length.
3304 // If any of these assumptions fail, we call the runtime system. 3487 // If any of these assumptions fail, we call the runtime system.
3305 3488
3306 const int kToOffset = 0 * kPointerSize; 3489 const int kToOffset = 0 * kPointerSize;
3307 const int kFromOffset = 1 * kPointerSize; 3490 const int kFromOffset = 1 * kPointerSize;
3308 const int kStringOffset = 2 * kPointerSize; 3491 const int kStringOffset = 2 * kPointerSize;
3309 3492
3310 __ Ldrd(r2, r3, MemOperand(sp, kToOffset)); 3493 __ LoadP(r5, MemOperand(sp, kToOffset));
3311 STATIC_ASSERT(kFromOffset == kToOffset + 4); 3494 __ LoadP(r6, MemOperand(sp, kFromOffset));
3312 STATIC_ASSERT(kSmiTag == 0);
3313 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
3314 3495
3315 // Arithmetic shift right by one un-smi-tags. In this case we rotate right 3496 // If either to or from had the smi tag bit set, then fail to generic runtime
3316 // instead because we bail out on non-smi values: ROR and ASR are equivalent 3497 __ JumpIfNotSmi(r5, &runtime);
3317 // for smis but they set the flags in a way that's easier to optimize. 3498 __ JumpIfNotSmi(r6, &runtime);
3318 __ mov(r2, Operand(r2, ROR, 1), SetCC); 3499 __ SmiUntag(r5);
3319 __ mov(r3, Operand(r3, ROR, 1), SetCC, cc); 3500 __ SmiUntag(r6, SetRC);
3320 // If either to or from had the smi tag bit set, then C is set now, and N 3501 // Both r5 and r6 are untagged integers.
3321 // has the same value: we rotated by 1, so the bottom bit is now the top bit. 3502
3322 // We want to bailout to runtime here if From is negative. In that case, the 3503 // We want to bailout to runtime here if From is negative.
3323 // next instruction is not executed and we fall through to bailing out to 3504 __ blt(&runtime, cr0); // From < 0.
3324 // runtime. 3505
3325 // Executed if both r2 and r3 are untagged integers. 3506 __ cmpl(r6, r5);
3326 __ sub(r2, r2, Operand(r3), SetCC, cc); 3507 __ bgt(&runtime); // Fail if from > to.
3327 // One of the above un-smis or the above SUB could have set N==1. 3508 __ sub(r5, r5, r6);
3328 __ b(mi, &runtime); // Either "from" or "to" is not an smi, or from > to.
3329 3509
3330 // Make sure first argument is a string. 3510 // Make sure first argument is a string.
3331 __ ldr(r0, MemOperand(sp, kStringOffset)); 3511 __ LoadP(r3, MemOperand(sp, kStringOffset));
3332 __ JumpIfSmi(r0, &runtime); 3512 __ JumpIfSmi(r3, &runtime);
3333 Condition is_string = masm->IsObjectStringType(r0, r1); 3513 Condition is_string = masm->IsObjectStringType(r3, r4);
3334 __ b(NegateCondition(is_string), &runtime); 3514 __ b(NegateCondition(is_string), &runtime, cr0);
3335 3515
3336 Label single_char; 3516 Label single_char;
3337 __ cmp(r2, Operand(1)); 3517 __ cmpi(r5, Operand(1));
3338 __ b(eq, &single_char); 3518 __ b(eq, &single_char);
3339 3519
3340 // Short-cut for the case of trivial substring. 3520 // Short-cut for the case of trivial substring.
3341 Label return_r0; 3521 Label return_r3;
3342 // r0: original string 3522 // r3: original string
3343 // r2: result string length 3523 // r5: result string length
3344 __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset)); 3524 __ LoadP(r7, FieldMemOperand(r3, String::kLengthOffset));
3345 __ cmp(r2, Operand(r4, ASR, 1)); 3525 __ SmiUntag(r0, r7);
3526 __ cmpl(r5, r0);
3346 // Return original string. 3527 // Return original string.
3347 __ b(eq, &return_r0); 3528 __ beq(&return_r3);
3348 // Longer than original string's length or negative: unsafe arguments. 3529 // Longer than original string's length or negative: unsafe arguments.
3349 __ b(hi, &runtime); 3530 __ bgt(&runtime);
3350 // Shorter than original string's length: an actual substring. 3531 // Shorter than original string's length: an actual substring.
3351 3532
3352 // Deal with different string types: update the index if necessary 3533 // Deal with different string types: update the index if necessary
3353 // and put the underlying string into r5. 3534 // and put the underlying string into r8.
3354 // r0: original string 3535 // r3: original string
3355 // r1: instance type 3536 // r4: instance type
3356 // r2: length 3537 // r5: length
3357 // r3: from index (untagged) 3538 // r6: from index (untagged)
3358 Label underlying_unpacked, sliced_string, seq_or_external_string; 3539 Label underlying_unpacked, sliced_string, seq_or_external_string;
3359 // If the string is not indirect, it can only be sequential or external. 3540 // If the string is not indirect, it can only be sequential or external.
3360 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); 3541 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
3361 STATIC_ASSERT(kIsIndirectStringMask != 0); 3542 STATIC_ASSERT(kIsIndirectStringMask != 0);
3362 __ tst(r1, Operand(kIsIndirectStringMask)); 3543 __ andi(r0, r4, Operand(kIsIndirectStringMask));
3363 __ b(eq, &seq_or_external_string); 3544 __ beq(&seq_or_external_string, cr0);
3364 3545
3365 __ tst(r1, Operand(kSlicedNotConsMask)); 3546 __ andi(r0, r4, Operand(kSlicedNotConsMask));
3366 __ b(ne, &sliced_string); 3547 __ bne(&sliced_string, cr0);
3367 // Cons string. Check whether it is flat, then fetch first part. 3548 // Cons string. Check whether it is flat, then fetch first part.
3368 __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset)); 3549 __ LoadP(r8, FieldMemOperand(r3, ConsString::kSecondOffset));
3369 __ CompareRoot(r5, Heap::kempty_stringRootIndex); 3550 __ CompareRoot(r8, Heap::kempty_stringRootIndex);
3370 __ b(ne, &runtime); 3551 __ bne(&runtime);
3371 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); 3552 __ LoadP(r8, FieldMemOperand(r3, ConsString::kFirstOffset));
3372 // Update instance type. 3553 // Update instance type.
3373 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); 3554 __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset));
3374 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3555 __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
3375 __ jmp(&underlying_unpacked); 3556 __ b(&underlying_unpacked);
3376 3557
3377 __ bind(&sliced_string); 3558 __ bind(&sliced_string);
3378 // Sliced string. Fetch parent and correct start index by offset. 3559 // Sliced string. Fetch parent and correct start index by offset.
3379 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); 3560 __ LoadP(r8, FieldMemOperand(r3, SlicedString::kParentOffset));
3380 __ ldr(r4, FieldMemOperand(r0, SlicedString::kOffsetOffset)); 3561 __ LoadP(r7, FieldMemOperand(r3, SlicedString::kOffsetOffset));
3381 __ add(r3, r3, Operand(r4, ASR, 1)); // Add offset to index. 3562 __ SmiUntag(r4, r7);
3563 __ add(r6, r6, r4); // Add offset to index.
3382 // Update instance type. 3564 // Update instance type.
3383 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); 3565 __ LoadP(r4, FieldMemOperand(r8, HeapObject::kMapOffset));
3384 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 3566 __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
3385 __ jmp(&underlying_unpacked); 3567 __ b(&underlying_unpacked);
3386 3568
3387 __ bind(&seq_or_external_string); 3569 __ bind(&seq_or_external_string);
3388 // Sequential or external string. Just move string to the expected register. 3570 // Sequential or external string. Just move string to the expected register.
3389 __ mov(r5, r0); 3571 __ mr(r8, r3);
3390 3572
3391 __ bind(&underlying_unpacked); 3573 __ bind(&underlying_unpacked);
3392 3574
3393 if (FLAG_string_slices) { 3575 if (FLAG_string_slices) {
3394 Label copy_routine; 3576 Label copy_routine;
3395 // r5: underlying subject string 3577 // r8: underlying subject string
3396 // r1: instance type of underlying subject string 3578 // r4: instance type of underlying subject string
3397 // r2: length 3579 // r5: length
3398 // r3: adjusted start index (untagged) 3580 // r6: adjusted start index (untagged)
3399 __ cmp(r2, Operand(SlicedString::kMinLength)); 3581 __ cmpi(r5, Operand(SlicedString::kMinLength));
3400 // Short slice. Copy instead of slicing. 3582 // Short slice. Copy instead of slicing.
3401 __ b(lt, &copy_routine); 3583 __ blt(&copy_routine);
3402 // Allocate new sliced string. At this point we do not reload the instance 3584 // Allocate new sliced string. At this point we do not reload the instance
3403 // type including the string encoding because we simply rely on the info 3585 // type including the string encoding because we simply rely on the info
3404 // provided by the original string. It does not matter if the original 3586 // provided by the original string. It does not matter if the original
3405 // string's encoding is wrong because we always have to recheck encoding of 3587 // string's encoding is wrong because we always have to recheck encoding of
3406 // the newly created string's parent anyways due to externalized strings. 3588 // the newly created string's parent anyways due to externalized strings.
3407 Label two_byte_slice, set_slice_header; 3589 Label two_byte_slice, set_slice_header;
3408 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0); 3590 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
3409 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); 3591 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
3410 __ tst(r1, Operand(kStringEncodingMask)); 3592 __ andi(r0, r4, Operand(kStringEncodingMask));
3411 __ b(eq, &two_byte_slice); 3593 __ beq(&two_byte_slice, cr0);
3412 __ AllocateAsciiSlicedString(r0, r2, r6, r4, &runtime); 3594 __ AllocateAsciiSlicedString(r3, r5, r9, r10, &runtime);
3413 __ jmp(&set_slice_header); 3595 __ b(&set_slice_header);
3414 __ bind(&two_byte_slice); 3596 __ bind(&two_byte_slice);
3415 __ AllocateTwoByteSlicedString(r0, r2, r6, r4, &runtime); 3597 __ AllocateTwoByteSlicedString(r3, r5, r9, r10, &runtime);
3416 __ bind(&set_slice_header); 3598 __ bind(&set_slice_header);
3417 __ mov(r3, Operand(r3, LSL, 1)); 3599 __ SmiTag(r6);
3418 __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); 3600 __ StoreP(r8, FieldMemOperand(r3, SlicedString::kParentOffset), r0);
3419 __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset)); 3601 __ StoreP(r6, FieldMemOperand(r3, SlicedString::kOffsetOffset), r0);
3420 __ jmp(&return_r0); 3602 __ b(&return_r3);
3421 3603
3422 __ bind(&copy_routine); 3604 __ bind(&copy_routine);
3423 } 3605 }
3424 3606
3425 // r5: underlying subject string 3607 // r8: underlying subject string
3426 // r1: instance type of underlying subject string 3608 // r4: instance type of underlying subject string
3427 // r2: length 3609 // r5: length
3428 // r3: adjusted start index (untagged) 3610 // r6: adjusted start index (untagged)
3429 Label two_byte_sequential, sequential_string, allocate_result; 3611 Label two_byte_sequential, sequential_string, allocate_result;
3430 STATIC_ASSERT(kExternalStringTag != 0); 3612 STATIC_ASSERT(kExternalStringTag != 0);
3431 STATIC_ASSERT(kSeqStringTag == 0); 3613 STATIC_ASSERT(kSeqStringTag == 0);
3432 __ tst(r1, Operand(kExternalStringTag)); 3614 __ andi(r0, r4, Operand(kExternalStringTag));
3433 __ b(eq, &sequential_string); 3615 __ beq(&sequential_string, cr0);
3434 3616
3435 // Handle external string. 3617 // Handle external string.
3436 // Rule out short external strings. 3618 // Rule out short external strings.
3437 STATIC_ASSERT(kShortExternalStringTag != 0); 3619 STATIC_ASSERT(kShortExternalStringTag != 0);
3438 __ tst(r1, Operand(kShortExternalStringTag)); 3620 __ andi(r0, r4, Operand(kShortExternalStringTag));
3439 __ b(ne, &runtime); 3621 __ bne(&runtime, cr0);
3440 __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset)); 3622 __ LoadP(r8, FieldMemOperand(r8, ExternalString::kResourceDataOffset));
3441 // r5 already points to the first character of underlying string. 3623 // r8 already points to the first character of underlying string.
3442 __ jmp(&allocate_result); 3624 __ b(&allocate_result);
3443 3625
3444 __ bind(&sequential_string); 3626 __ bind(&sequential_string);
3445 // Locate first character of underlying subject string. 3627 // Locate first character of underlying subject string.
3446 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 3628 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
3447 __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3629 __ addi(r8, r8, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3448 3630
3449 __ bind(&allocate_result); 3631 __ bind(&allocate_result);
3450 // Sequential acii string. Allocate the result. 3632 // Sequential acii string. Allocate the result.
3451 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); 3633 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
3452 __ tst(r1, Operand(kStringEncodingMask)); 3634 __ andi(r0, r4, Operand(kStringEncodingMask));
3453 __ b(eq, &two_byte_sequential); 3635 __ beq(&two_byte_sequential, cr0);
3454 3636
3455 // Allocate and copy the resulting ASCII string. 3637 // Allocate and copy the resulting ASCII string.
3456 __ AllocateAsciiString(r0, r2, r4, r6, r1, &runtime); 3638 __ AllocateAsciiString(r3, r5, r7, r9, r10, &runtime);
3457 3639
3458 // Locate first character of substring to copy. 3640 // Locate first character of substring to copy.
3459 __ add(r5, r5, r3); 3641 __ add(r8, r8, r6);
3460 // Locate first character of result. 3642 // Locate first character of result.
3461 __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3643 __ addi(r4, r3, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3462 3644
3463 // r0: result string 3645 // r3: result string
3464 // r1: first character of result string 3646 // r4: first character of result string
3465 // r2: result string length 3647 // r5: result string length
3466 // r5: first character of substring to copy 3648 // r8: first character of substring to copy
3467 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); 3649 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3468 StringHelper::GenerateCopyCharacters( 3650 StringHelper::GenerateCopyCharacters(
3469 masm, r1, r5, r2, r3, String::ONE_BYTE_ENCODING); 3651 masm, r4, r8, r5, r6, String::ONE_BYTE_ENCODING);
3470 __ jmp(&return_r0); 3652 __ b(&return_r3);
3471 3653
3472 // Allocate and copy the resulting two-byte string. 3654 // Allocate and copy the resulting two-byte string.
3473 __ bind(&two_byte_sequential); 3655 __ bind(&two_byte_sequential);
3474 __ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime); 3656 __ AllocateTwoByteString(r3, r5, r7, r9, r10, &runtime);
3475 3657
3476 // Locate first character of substring to copy. 3658 // Locate first character of substring to copy.
3477 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 3659 __ ShiftLeftImm(r4, r6, Operand(1));
3478 __ add(r5, r5, Operand(r3, LSL, 1)); 3660 __ add(r8, r8, r4);
3479 // Locate first character of result. 3661 // Locate first character of result.
3480 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 3662 __ addi(r4, r3, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3481 3663
3482 // r0: result string. 3664 // r3: result string.
3483 // r1: first character of result. 3665 // r4: first character of result.
3484 // r2: result length. 3666 // r5: result length.
3485 // r5: first character of substring to copy. 3667 // r8: first character of substring to copy.
3486 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 3668 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
3487 StringHelper::GenerateCopyCharacters( 3669 StringHelper::GenerateCopyCharacters(
3488 masm, r1, r5, r2, r3, String::TWO_BYTE_ENCODING); 3670 masm, r4, r8, r5, r6, String::TWO_BYTE_ENCODING);
3489 3671
3490 __ bind(&return_r0); 3672 __ bind(&return_r3);
3491 Counters* counters = isolate()->counters(); 3673 Counters* counters = isolate()->counters();
3492 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); 3674 __ IncrementCounter(counters->sub_string_native(), 1, r6, r7);
3493 __ Drop(3); 3675 __ Drop(3);
3494 __ Ret(); 3676 __ Ret();
3495 3677
3496 // Just jump to runtime to create the sub string. 3678 // Just jump to runtime to create the sub string.
3497 __ bind(&runtime); 3679 __ bind(&runtime);
3498 __ TailCallRuntime(Runtime::kSubString, 3, 1); 3680 __ TailCallRuntime(Runtime::kSubString, 3, 1);
3499 3681
3500 __ bind(&single_char); 3682 __ bind(&single_char);
3501 // r0: original string 3683 // r3: original string
3502 // r1: instance type 3684 // r4: instance type
3503 // r2: length 3685 // r5: length
3504 // r3: from index (untagged) 3686 // r6: from index (untagged)
3505 __ SmiTag(r3, r3); 3687 __ SmiTag(r6, r6);
3506 StringCharAtGenerator generator( 3688 StringCharAtGenerator generator(
3507 r0, r3, r2, r0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER); 3689 r3, r6, r5, r3, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
3508 generator.GenerateFast(masm); 3690 generator.GenerateFast(masm);
3509 __ Drop(3); 3691 __ Drop(3);
3510 __ Ret(); 3692 __ Ret();
3511 generator.SkipSlow(masm, &runtime); 3693 generator.SkipSlow(masm, &runtime);
3512 } 3694 }
3513 3695
3514 3696
3515 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm, 3697 void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
3516 Register left, 3698 Register left,
3517 Register right, 3699 Register right,
3518 Register scratch1, 3700 Register scratch1,
3519 Register scratch2, 3701 Register scratch2) {
3520 Register scratch3) {
3521 Register length = scratch1; 3702 Register length = scratch1;
3522 3703
3523 // Compare lengths. 3704 // Compare lengths.
3524 Label strings_not_equal, check_zero_length; 3705 Label strings_not_equal, check_zero_length;
3525 __ ldr(length, FieldMemOperand(left, String::kLengthOffset)); 3706 __ LoadP(length, FieldMemOperand(left, String::kLengthOffset));
3526 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); 3707 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
3527 __ cmp(length, scratch2); 3708 __ cmp(length, scratch2);
3528 __ b(eq, &check_zero_length); 3709 __ beq(&check_zero_length);
3529 __ bind(&strings_not_equal); 3710 __ bind(&strings_not_equal);
3530 __ mov(r0, Operand(Smi::FromInt(NOT_EQUAL))); 3711 __ LoadSmiLiteral(r3, Smi::FromInt(NOT_EQUAL));
3531 __ Ret(); 3712 __ Ret();
3532 3713
3533 // Check if the length is zero. 3714 // Check if the length is zero.
3534 Label compare_chars; 3715 Label compare_chars;
3535 __ bind(&check_zero_length); 3716 __ bind(&check_zero_length);
3536 STATIC_ASSERT(kSmiTag == 0); 3717 STATIC_ASSERT(kSmiTag == 0);
3537 __ cmp(length, Operand::Zero()); 3718 __ cmpi(length, Operand::Zero());
3538 __ b(ne, &compare_chars); 3719 __ bne(&compare_chars);
3539 __ mov(r0, Operand(Smi::FromInt(EQUAL))); 3720 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
3540 __ Ret(); 3721 __ Ret();
3541 3722
3542 // Compare characters. 3723 // Compare characters.
3543 __ bind(&compare_chars); 3724 __ bind(&compare_chars);
3544 GenerateAsciiCharsCompareLoop(masm, 3725 GenerateAsciiCharsCompareLoop(masm,
3545 left, right, length, scratch2, scratch3, 3726 left, right, length, scratch2,
3546 &strings_not_equal); 3727 &strings_not_equal);
3547 3728
3548 // Characters are equal. 3729 // Characters are equal.
3549 __ mov(r0, Operand(Smi::FromInt(EQUAL))); 3730 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
3550 __ Ret(); 3731 __ Ret();
3551 } 3732 }
3552 3733
3553 3734
3554 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 3735 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
3555 Register left, 3736 Register left,
3556 Register right, 3737 Register right,
3557 Register scratch1, 3738 Register scratch1,
3558 Register scratch2, 3739 Register scratch2,
3559 Register scratch3, 3740 Register scratch3) {
3560 Register scratch4) { 3741 Label skip, result_not_equal, compare_lengths;
3561 Label result_not_equal, compare_lengths;
3562 // Find minimum length and length difference. 3742 // Find minimum length and length difference.
3563 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset)); 3743 __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset));
3564 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); 3744 __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
3565 __ sub(scratch3, scratch1, Operand(scratch2), SetCC); 3745 __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC);
3566 Register length_delta = scratch3; 3746 Register length_delta = scratch3;
3567 __ mov(scratch1, scratch2, LeaveCC, gt); 3747 __ ble(&skip, cr0);
3748 __ mr(scratch1, scratch2);
3749 __ bind(&skip);
3568 Register min_length = scratch1; 3750 Register min_length = scratch1;
3569 STATIC_ASSERT(kSmiTag == 0); 3751 STATIC_ASSERT(kSmiTag == 0);
3570 __ cmp(min_length, Operand::Zero()); 3752 __ cmpi(min_length, Operand::Zero());
3571 __ b(eq, &compare_lengths); 3753 __ beq(&compare_lengths);
3572 3754
3573 // Compare loop. 3755 // Compare loop.
3574 GenerateAsciiCharsCompareLoop(masm, 3756 GenerateAsciiCharsCompareLoop(masm,
3575 left, right, min_length, scratch2, scratch4, 3757 left, right, min_length, scratch2,
3576 &result_not_equal); 3758 &result_not_equal);
3577 3759
3578 // Compare lengths - strings up to min-length are equal. 3760 // Compare lengths - strings up to min-length are equal.
3579 __ bind(&compare_lengths); 3761 __ bind(&compare_lengths);
3580 ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0)); 3762 ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
3581 // Use length_delta as result if it's zero. 3763 // Use length_delta as result if it's zero.
3582 __ mov(r0, Operand(length_delta), SetCC); 3764 __ mr(r3, length_delta);
3765 __ cmpi(r3, Operand::Zero());
3583 __ bind(&result_not_equal); 3766 __ bind(&result_not_equal);
3584 // Conditionally update the result based either on length_delta or 3767 // Conditionally update the result based either on length_delta or
3585 // the last comparion performed in the loop above. 3768 // the last comparion performed in the loop above.
3586 __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt); 3769 Label less_equal, equal;
3587 __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt); 3770 __ ble(&less_equal);
3771 __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
3772 __ Ret();
3773 __ bind(&less_equal);
3774 __ beq(&equal);
3775 __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
3776 __ bind(&equal);
3588 __ Ret(); 3777 __ Ret();
3589 } 3778 }
3590 3779
3591 3780
3592 void StringCompareStub::GenerateAsciiCharsCompareLoop( 3781 void StringCompareStub::GenerateAsciiCharsCompareLoop(
3593 MacroAssembler* masm, 3782 MacroAssembler* masm,
3594 Register left, 3783 Register left,
3595 Register right, 3784 Register right,
3596 Register length, 3785 Register length,
3597 Register scratch1, 3786 Register scratch1,
3598 Register scratch2,
3599 Label* chars_not_equal) { 3787 Label* chars_not_equal) {
3600 // Change index to run from -length to -1 by adding length to string 3788 // Change index to run from -length to -1 by adding length to string
3601 // start. This means that loop ends when index reaches zero, which 3789 // start. This means that loop ends when index reaches zero, which
3602 // doesn't need an additional compare. 3790 // doesn't need an additional compare.
3603 __ SmiUntag(length); 3791 __ SmiUntag(length);
3604 __ add(scratch1, length, 3792 __ addi(scratch1, length,
3605 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3793 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3606 __ add(left, left, Operand(scratch1)); 3794 __ add(left, left, scratch1);
3607 __ add(right, right, Operand(scratch1)); 3795 __ add(right, right, scratch1);
3608 __ rsb(length, length, Operand::Zero()); 3796 __ subfic(length, length, Operand::Zero());
3609 Register index = length; // index = -length; 3797 Register index = length; // index = -length;
3610 3798
3611 // Compare loop. 3799 // Compare loop.
3612 Label loop; 3800 Label loop;
3613 __ bind(&loop); 3801 __ bind(&loop);
3614 __ ldrb(scratch1, MemOperand(left, index)); 3802 __ lbzx(scratch1, MemOperand(left, index));
3615 __ ldrb(scratch2, MemOperand(right, index)); 3803 __ lbzx(r0, MemOperand(right, index));
3616 __ cmp(scratch1, scratch2); 3804 __ cmp(scratch1, r0);
3617 __ b(ne, chars_not_equal); 3805 __ bne(chars_not_equal);
3618 __ add(index, index, Operand(1), SetCC); 3806 __ addi(index, index, Operand(1));
3619 __ b(ne, &loop); 3807 __ cmpi(index, Operand::Zero());
3808 __ bne(&loop);
3620 } 3809 }
3621 3810
3622 3811
3623 void StringCompareStub::Generate(MacroAssembler* masm) { 3812 void StringCompareStub::Generate(MacroAssembler* masm) {
3624 Label runtime; 3813 Label runtime;
3625 3814
3626 Counters* counters = isolate()->counters(); 3815 Counters* counters = isolate()->counters();
3627 3816
3628 // Stack frame on entry. 3817 // Stack frame on entry.
3629 // sp[0]: right string 3818 // sp[0]: right string
3630 // sp[4]: left string 3819 // sp[4]: left string
3631 __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1. 3820 __ LoadP(r3, MemOperand(sp)); // Load right in r3, left in r4.
3821 __ LoadP(r4, MemOperand(sp, kPointerSize));
3632 3822
3633 Label not_same; 3823 Label not_same;
3634 __ cmp(r0, r1); 3824 __ cmp(r3, r4);
3635 __ b(ne, &not_same); 3825 __ bne(&not_same);
3636 STATIC_ASSERT(EQUAL == 0); 3826 STATIC_ASSERT(EQUAL == 0);
3637 STATIC_ASSERT(kSmiTag == 0); 3827 STATIC_ASSERT(kSmiTag == 0);
3638 __ mov(r0, Operand(Smi::FromInt(EQUAL))); 3828 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
3639 __ IncrementCounter(counters->string_compare_native(), 1, r1, r2); 3829 __ IncrementCounter(counters->string_compare_native(), 1, r4, r5);
3640 __ add(sp, sp, Operand(2 * kPointerSize)); 3830 __ addi(sp, sp, Operand(2 * kPointerSize));
3641 __ Ret(); 3831 __ Ret();
3642 3832
3643 __ bind(&not_same); 3833 __ bind(&not_same);
3644 3834
3645 // Check that both objects are sequential ASCII strings. 3835 // Check that both objects are sequential ASCII strings.
3646 __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime); 3836 __ JumpIfNotBothSequentialAsciiStrings(r4, r3, r5, r6, &runtime);
3647 3837
3648 // Compare flat ASCII strings natively. Remove arguments from stack first. 3838 // Compare flat ASCII strings natively. Remove arguments from stack first.
3649 __ IncrementCounter(counters->string_compare_native(), 1, r2, r3); 3839 __ IncrementCounter(counters->string_compare_native(), 1, r5, r6);
3650 __ add(sp, sp, Operand(2 * kPointerSize)); 3840 __ addi(sp, sp, Operand(2 * kPointerSize));
3651 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); 3841 GenerateCompareFlatAsciiStrings(masm, r4, r3, r5, r6, r7);
3652 3842
3653 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 3843 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
3654 // tagged as a small integer. 3844 // tagged as a small integer.
3655 __ bind(&runtime); 3845 __ bind(&runtime);
3656 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 3846 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
3657 } 3847 }
3658 3848
3659 3849
3660 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { 3850 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
3661 // ----------- S t a t e ------------- 3851 // ----------- S t a t e -------------
3662 // -- r1 : left 3852 // -- r4 : left
3663 // -- r0 : right 3853 // -- r3 : right
3664 // -- lr : return address 3854 // -- lr : return address
3665 // ----------------------------------- 3855 // -----------------------------------
3666 3856
3667 // Load r2 with the allocation site. We stick an undefined dummy value here 3857 // Load r5 with the allocation site. We stick an undefined dummy value here
3668 // and replace it with the real allocation site later when we instantiate this 3858 // and replace it with the real allocation site later when we instantiate this
3669 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). 3859 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
3670 __ Move(r2, handle(isolate()->heap()->undefined_value())); 3860 __ Move(r5, handle(isolate()->heap()->undefined_value()));
3671 3861
3672 // Make sure that we actually patched the allocation site. 3862 // Make sure that we actually patched the allocation site.
3673 if (FLAG_debug_code) { 3863 if (FLAG_debug_code) {
3674 __ tst(r2, Operand(kSmiTagMask)); 3864 __ TestIfSmi(r5, r0);
3675 __ Assert(ne, kExpectedAllocationSite); 3865 __ Assert(ne, kExpectedAllocationSite, cr0);
3676 __ push(r2); 3866 __ push(r5);
3677 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); 3867 __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset));
3678 __ LoadRoot(ip, Heap::kAllocationSiteMapRootIndex); 3868 __ LoadRoot(ip, Heap::kAllocationSiteMapRootIndex);
3679 __ cmp(r2, ip); 3869 __ cmp(r5, ip);
3680 __ pop(r2); 3870 __ pop(r5);
3681 __ Assert(eq, kExpectedAllocationSite); 3871 __ Assert(eq, kExpectedAllocationSite);
3682 } 3872 }
3683 3873
3684 // Tail call into the stub that handles binary operations with allocation 3874 // Tail call into the stub that handles binary operations with allocation
3685 // sites. 3875 // sites.
3686 BinaryOpWithAllocationSiteStub stub(isolate(), state_); 3876 BinaryOpWithAllocationSiteStub stub(isolate(), state_);
3687 __ TailCallStub(&stub); 3877 __ TailCallStub(&stub);
3688 } 3878 }
3689 3879
3690 3880
3691 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { 3881 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
3692 ASSERT(state_ == CompareIC::SMI); 3882 ASSERT(state_ == CompareIC::SMI);
3693 Label miss; 3883 Label miss;
3694 __ orr(r2, r1, r0); 3884 __ orx(r5, r4, r3);
3695 __ JumpIfNotSmi(r2, &miss); 3885 __ JumpIfNotSmi(r5, &miss);
3696 3886
3697 if (GetCondition() == eq) { 3887 if (GetCondition() == eq) {
3698 // For equality we do not care about the sign of the result. 3888 // For equality we do not care about the sign of the result.
3699 __ sub(r0, r0, r1, SetCC); 3889 // __ sub(r3, r3, r4, SetCC);
3890 __ sub(r3, r3, r4);
3700 } else { 3891 } else {
3701 // Untag before subtracting to avoid handling overflow. 3892 // Untag before subtracting to avoid handling overflow.
3702 __ SmiUntag(r1); 3893 __ SmiUntag(r4);
3703 __ sub(r0, r1, Operand::SmiUntag(r0)); 3894 __ SmiUntag(r3);
3895 __ sub(r3, r4, r3);
3704 } 3896 }
3705 __ Ret(); 3897 __ Ret();
3706 3898
3707 __ bind(&miss); 3899 __ bind(&miss);
3708 GenerateMiss(masm); 3900 GenerateMiss(masm);
3709 } 3901 }
3710 3902
3711 3903
3712 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) { 3904 void ICCompareStub::GenerateNumbers(MacroAssembler* masm) {
3713 ASSERT(state_ == CompareIC::NUMBER); 3905 ASSERT(state_ == CompareIC::NUMBER);
3714 3906
3715 Label generic_stub; 3907 Label generic_stub;
3716 Label unordered, maybe_undefined1, maybe_undefined2; 3908 Label unordered, maybe_undefined1, maybe_undefined2;
3717 Label miss; 3909 Label miss;
3910 Label equal, less_than;
3718 3911
3719 if (left_ == CompareIC::SMI) { 3912 if (left_ == CompareIC::SMI) {
3720 __ JumpIfNotSmi(r1, &miss); 3913 __ JumpIfNotSmi(r4, &miss);
3721 } 3914 }
3722 if (right_ == CompareIC::SMI) { 3915 if (right_ == CompareIC::SMI) {
3723 __ JumpIfNotSmi(r0, &miss); 3916 __ JumpIfNotSmi(r3, &miss);
3724 } 3917 }
3725 3918
3726 // Inlining the double comparison and falling back to the general compare 3919 // Inlining the double comparison and falling back to the general compare
3727 // stub if NaN is involved. 3920 // stub if NaN is involved.
3728 // Load left and right operand. 3921 // Load left and right operand.
3729 Label done, left, left_smi, right_smi; 3922 Label done, left, left_smi, right_smi;
3730 __ JumpIfSmi(r0, &right_smi); 3923 __ JumpIfSmi(r3, &right_smi);
3731 __ CheckMap(r0, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1, 3924 __ CheckMap(r3, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined1,
3732 DONT_DO_SMI_CHECK); 3925 DONT_DO_SMI_CHECK);
3733 __ sub(r2, r0, Operand(kHeapObjectTag)); 3926 __ lfd(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
3734 __ vldr(d1, r2, HeapNumber::kValueOffset);
3735 __ b(&left); 3927 __ b(&left);
3736 __ bind(&right_smi); 3928 __ bind(&right_smi);
3737 __ SmiToDouble(d1, r0); 3929 __ SmiToDouble(d1, r3);
3738 3930
3739 __ bind(&left); 3931 __ bind(&left);
3740 __ JumpIfSmi(r1, &left_smi); 3932 __ JumpIfSmi(r4, &left_smi);
3741 __ CheckMap(r1, r2, Heap::kHeapNumberMapRootIndex, &maybe_undefined2, 3933 __ CheckMap(r4, r5, Heap::kHeapNumberMapRootIndex, &maybe_undefined2,
3742 DONT_DO_SMI_CHECK); 3934 DONT_DO_SMI_CHECK);
3743 __ sub(r2, r1, Operand(kHeapObjectTag)); 3935 __ lfd(d0, FieldMemOperand(r4, HeapNumber::kValueOffset));
3744 __ vldr(d0, r2, HeapNumber::kValueOffset);
3745 __ b(&done); 3936 __ b(&done);
3746 __ bind(&left_smi); 3937 __ bind(&left_smi);
3747 __ SmiToDouble(d0, r1); 3938 __ SmiToDouble(d0, r4);
3748 3939
3749 __ bind(&done); 3940 __ bind(&done);
3750 // Compare operands. 3941
3751 __ VFPCompareAndSetFlags(d0, d1); 3942 // Compare operands
3943 __ fcmpu(d0, d1);
3752 3944
3753 // Don't base result on status bits when a NaN is involved. 3945 // Don't base result on status bits when a NaN is involved.
3754 __ b(vs, &unordered); 3946 __ bunordered(&unordered);
3755 3947
3756 // Return a result of -1, 0, or 1, based on status bits. 3948 // Return a result of -1, 0, or 1, based on status bits.
3757 __ mov(r0, Operand(EQUAL), LeaveCC, eq); 3949 __ beq(&equal);
3758 __ mov(r0, Operand(LESS), LeaveCC, lt); 3950 __ blt(&less_than);
3759 __ mov(r0, Operand(GREATER), LeaveCC, gt); 3951 // assume greater than
3952 __ li(r3, Operand(GREATER));
3953 __ Ret();
3954 __ bind(&equal);
3955 __ li(r3, Operand(EQUAL));
3956 __ Ret();
3957 __ bind(&less_than);
3958 __ li(r3, Operand(LESS));
3760 __ Ret(); 3959 __ Ret();
3761 3960
3762 __ bind(&unordered); 3961 __ bind(&unordered);
3763 __ bind(&generic_stub); 3962 __ bind(&generic_stub);
3764 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC, 3963 ICCompareStub stub(isolate(), op_, CompareIC::GENERIC, CompareIC::GENERIC,
3765 CompareIC::GENERIC); 3964 CompareIC::GENERIC);
3766 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 3965 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
3767 3966
3768 __ bind(&maybe_undefined1); 3967 __ bind(&maybe_undefined1);
3769 if (Token::IsOrderedRelationalCompareOp(op_)) { 3968 if (Token::IsOrderedRelationalCompareOp(op_)) {
3770 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); 3969 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
3771 __ b(ne, &miss); 3970 __ bne(&miss);
3772 __ JumpIfSmi(r1, &unordered); 3971 __ JumpIfSmi(r4, &unordered);
3773 __ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE); 3972 __ CompareObjectType(r4, r5, r5, HEAP_NUMBER_TYPE);
3774 __ b(ne, &maybe_undefined2); 3973 __ bne(&maybe_undefined2);
3775 __ jmp(&unordered); 3974 __ b(&unordered);
3776 } 3975 }
3777 3976
3778 __ bind(&maybe_undefined2); 3977 __ bind(&maybe_undefined2);
3779 if (Token::IsOrderedRelationalCompareOp(op_)) { 3978 if (Token::IsOrderedRelationalCompareOp(op_)) {
3780 __ CompareRoot(r1, Heap::kUndefinedValueRootIndex); 3979 __ CompareRoot(r4, Heap::kUndefinedValueRootIndex);
3781 __ b(eq, &unordered); 3980 __ beq(&unordered);
3782 } 3981 }
3783 3982
3784 __ bind(&miss); 3983 __ bind(&miss);
3785 GenerateMiss(masm); 3984 GenerateMiss(masm);
3786 } 3985 }
3787 3986
3788 3987
3789 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { 3988 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) {
3790 ASSERT(state_ == CompareIC::INTERNALIZED_STRING); 3989 ASSERT(state_ == CompareIC::INTERNALIZED_STRING);
3791 Label miss; 3990 Label miss, not_equal;
3792 3991
3793 // Registers containing left and right operands respectively. 3992 // Registers containing left and right operands respectively.
3794 Register left = r1; 3993 Register left = r4;
3795 Register right = r0; 3994 Register right = r3;
3796 Register tmp1 = r2; 3995 Register tmp1 = r5;
3797 Register tmp2 = r3; 3996 Register tmp2 = r6;
3798 3997
3799 // Check that both operands are heap objects. 3998 // Check that both operands are heap objects.
3800 __ JumpIfEitherSmi(left, right, &miss); 3999 __ JumpIfEitherSmi(left, right, &miss);
3801 4000
3802 // Check that both operands are internalized strings. 4001 // Check that both operands are symbols.
3803 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 4002 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3804 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 4003 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3805 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 4004 __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3806 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 4005 __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3807 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); 4006 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
3808 __ orr(tmp1, tmp1, Operand(tmp2)); 4007 __ orx(tmp1, tmp1, tmp2);
3809 __ tst(tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask)); 4008 __ andi(r0, tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask));
3810 __ b(ne, &miss); 4009 __ bne(&miss, cr0);
3811 4010
3812 // Internalized strings are compared by identity. 4011 // Internalized strings are compared by identity.
3813 __ cmp(left, right); 4012 __ cmp(left, right);
3814 // Make sure r0 is non-zero. At this point input operands are 4013 __ bne(&not_equal);
4014 // Make sure r3 is non-zero. At this point input operands are
3815 // guaranteed to be non-zero. 4015 // guaranteed to be non-zero.
3816 ASSERT(right.is(r0)); 4016 ASSERT(right.is(r3));
3817 STATIC_ASSERT(EQUAL == 0); 4017 STATIC_ASSERT(EQUAL == 0);
3818 STATIC_ASSERT(kSmiTag == 0); 4018 STATIC_ASSERT(kSmiTag == 0);
3819 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 4019 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
4020 __ bind(&not_equal);
3820 __ Ret(); 4021 __ Ret();
3821 4022
3822 __ bind(&miss); 4023 __ bind(&miss);
3823 GenerateMiss(masm); 4024 GenerateMiss(masm);
3824 } 4025 }
3825 4026
3826 4027
3827 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) { 4028 void ICCompareStub::GenerateUniqueNames(MacroAssembler* masm) {
3828 ASSERT(state_ == CompareIC::UNIQUE_NAME); 4029 ASSERT(state_ == CompareIC::UNIQUE_NAME);
3829 ASSERT(GetCondition() == eq); 4030 ASSERT(GetCondition() == eq);
3830 Label miss; 4031 Label miss;
3831 4032
3832 // Registers containing left and right operands respectively. 4033 // Registers containing left and right operands respectively.
3833 Register left = r1; 4034 Register left = r4;
3834 Register right = r0; 4035 Register right = r3;
3835 Register tmp1 = r2; 4036 Register tmp1 = r5;
3836 Register tmp2 = r3; 4037 Register tmp2 = r6;
3837 4038
3838 // Check that both operands are heap objects. 4039 // Check that both operands are heap objects.
3839 __ JumpIfEitherSmi(left, right, &miss); 4040 __ JumpIfEitherSmi(left, right, &miss);
3840 4041
3841 // Check that both operands are unique names. This leaves the instance 4042 // Check that both operands are unique names. This leaves the instance
3842 // types loaded in tmp1 and tmp2. 4043 // types loaded in tmp1 and tmp2.
3843 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 4044 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3844 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 4045 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3845 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 4046 __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3846 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 4047 __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3847 4048
3848 __ JumpIfNotUniqueName(tmp1, &miss); 4049 __ JumpIfNotUniqueName(tmp1, &miss);
3849 __ JumpIfNotUniqueName(tmp2, &miss); 4050 __ JumpIfNotUniqueName(tmp2, &miss);
3850 4051
3851 // Unique names are compared by identity. 4052 // Unique names are compared by identity.
3852 __ cmp(left, right); 4053 __ cmp(left, right);
3853 // Make sure r0 is non-zero. At this point input operands are 4054 __ bne(&miss);
4055 // Make sure r3 is non-zero. At this point input operands are
3854 // guaranteed to be non-zero. 4056 // guaranteed to be non-zero.
3855 ASSERT(right.is(r0)); 4057 ASSERT(right.is(r3));
3856 STATIC_ASSERT(EQUAL == 0); 4058 STATIC_ASSERT(EQUAL == 0);
3857 STATIC_ASSERT(kSmiTag == 0); 4059 STATIC_ASSERT(kSmiTag == 0);
3858 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 4060 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
3859 __ Ret(); 4061 __ Ret();
3860 4062
3861 __ bind(&miss); 4063 __ bind(&miss);
3862 GenerateMiss(masm); 4064 GenerateMiss(masm);
3863 } 4065 }
3864 4066
3865 4067
3866 void ICCompareStub::GenerateStrings(MacroAssembler* masm) { 4068 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
3867 ASSERT(state_ == CompareIC::STRING); 4069 ASSERT(state_ == CompareIC::STRING);
3868 Label miss; 4070 Label miss, not_identical, is_symbol;
3869 4071
3870 bool equality = Token::IsEqualityOp(op_); 4072 bool equality = Token::IsEqualityOp(op_);
3871 4073
3872 // Registers containing left and right operands respectively. 4074 // Registers containing left and right operands respectively.
3873 Register left = r1; 4075 Register left = r4;
3874 Register right = r0; 4076 Register right = r3;
3875 Register tmp1 = r2; 4077 Register tmp1 = r5;
3876 Register tmp2 = r3; 4078 Register tmp2 = r6;
3877 Register tmp3 = r4; 4079 Register tmp3 = r7;
3878 Register tmp4 = r5; 4080 Register tmp4 = r8;
3879 4081
3880 // Check that both operands are heap objects. 4082 // Check that both operands are heap objects.
3881 __ JumpIfEitherSmi(left, right, &miss); 4083 __ JumpIfEitherSmi(left, right, &miss);
3882 4084
3883 // Check that both operands are strings. This leaves the instance 4085 // Check that both operands are strings. This leaves the instance
3884 // types loaded in tmp1 and tmp2. 4086 // types loaded in tmp1 and tmp2.
3885 __ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset)); 4087 __ LoadP(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
3886 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 4088 __ LoadP(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3887 __ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset)); 4089 __ lbz(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
3888 __ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset)); 4090 __ lbz(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
3889 STATIC_ASSERT(kNotStringTag != 0); 4091 STATIC_ASSERT(kNotStringTag != 0);
3890 __ orr(tmp3, tmp1, tmp2); 4092 __ orx(tmp3, tmp1, tmp2);
3891 __ tst(tmp3, Operand(kIsNotStringMask)); 4093 __ andi(r0, tmp3, Operand(kIsNotStringMask));
3892 __ b(ne, &miss); 4094 __ bne(&miss, cr0);
3893 4095
3894 // Fast check for identical strings. 4096 // Fast check for identical strings.
3895 __ cmp(left, right); 4097 __ cmp(left, right);
3896 STATIC_ASSERT(EQUAL == 0); 4098 STATIC_ASSERT(EQUAL == 0);
3897 STATIC_ASSERT(kSmiTag == 0); 4099 STATIC_ASSERT(kSmiTag == 0);
3898 __ mov(r0, Operand(Smi::FromInt(EQUAL)), LeaveCC, eq); 4100 __ bne(&not_identical);
3899 __ Ret(eq); 4101 __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
4102 __ Ret();
4103 __ bind(&not_identical);
3900 4104
3901 // Handle not identical strings. 4105 // Handle not identical strings.
3902 4106
3903 // Check that both strings are internalized strings. If they are, we're done 4107 // Check that both strings are internalized strings. If they are, we're done
3904 // because we already know they are not identical. We know they are both 4108 // because we already know they are not identical. We know they are both
3905 // strings. 4109 // strings.
3906 if (equality) { 4110 if (equality) {
3907 ASSERT(GetCondition() == eq); 4111 ASSERT(GetCondition() == eq);
3908 STATIC_ASSERT(kInternalizedTag == 0); 4112 STATIC_ASSERT(kInternalizedTag == 0);
3909 __ orr(tmp3, tmp1, Operand(tmp2)); 4113 __ orx(tmp3, tmp1, tmp2);
3910 __ tst(tmp3, Operand(kIsNotInternalizedMask)); 4114 __ andi(r0, tmp3, Operand(kIsNotInternalizedMask));
3911 // Make sure r0 is non-zero. At this point input operands are 4115 __ bne(&is_symbol, cr0);
4116 // Make sure r3 is non-zero. At this point input operands are
3912 // guaranteed to be non-zero. 4117 // guaranteed to be non-zero.
3913 ASSERT(right.is(r0)); 4118 ASSERT(right.is(r3));
3914 __ Ret(eq); 4119 __ Ret();
4120 __ bind(&is_symbol);
3915 } 4121 }
3916 4122
3917 // Check that both strings are sequential ASCII. 4123 // Check that both strings are sequential ASCII.
3918 Label runtime; 4124 Label runtime;
3919 __ JumpIfBothInstanceTypesAreNotSequentialAscii( 4125 __ JumpIfBothInstanceTypesAreNotSequentialAscii(
3920 tmp1, tmp2, tmp3, tmp4, &runtime); 4126 tmp1, tmp2, tmp3, tmp4, &runtime);
3921 4127
3922 // Compare flat ASCII strings. Returns when done. 4128 // Compare flat ASCII strings. Returns when done.
3923 if (equality) { 4129 if (equality) {
3924 StringCompareStub::GenerateFlatAsciiStringEquals( 4130 StringCompareStub::GenerateFlatAsciiStringEquals(
3925 masm, left, right, tmp1, tmp2, tmp3); 4131 masm, left, right, tmp1, tmp2);
3926 } else { 4132 } else {
3927 StringCompareStub::GenerateCompareFlatAsciiStrings( 4133 StringCompareStub::GenerateCompareFlatAsciiStrings(
3928 masm, left, right, tmp1, tmp2, tmp3, tmp4); 4134 masm, left, right, tmp1, tmp2, tmp3);
3929 } 4135 }
3930 4136
3931 // Handle more complex cases in runtime. 4137 // Handle more complex cases in runtime.
3932 __ bind(&runtime); 4138 __ bind(&runtime);
3933 __ Push(left, right); 4139 __ Push(left, right);
3934 if (equality) { 4140 if (equality) {
3935 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); 4141 __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
3936 } else { 4142 } else {
3937 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 4143 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
3938 } 4144 }
3939 4145
3940 __ bind(&miss); 4146 __ bind(&miss);
3941 GenerateMiss(masm); 4147 GenerateMiss(masm);
3942 } 4148 }
3943 4149
3944 4150
3945 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 4151 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
3946 ASSERT(state_ == CompareIC::OBJECT); 4152 ASSERT(state_ == CompareIC::OBJECT);
3947 Label miss; 4153 Label miss;
3948 __ and_(r2, r1, Operand(r0)); 4154 __ and_(r5, r4, r3);
3949 __ JumpIfSmi(r2, &miss); 4155 __ JumpIfSmi(r5, &miss);
3950 4156
3951 __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); 4157 __ CompareObjectType(r3, r5, r5, JS_OBJECT_TYPE);
3952 __ b(ne, &miss); 4158 __ bne(&miss);
3953 __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); 4159 __ CompareObjectType(r4, r5, r5, JS_OBJECT_TYPE);
3954 __ b(ne, &miss); 4160 __ bne(&miss);
3955 4161
3956 ASSERT(GetCondition() == eq); 4162 ASSERT(GetCondition() == eq);
3957 __ sub(r0, r0, Operand(r1)); 4163 __ sub(r3, r3, r4);
3958 __ Ret(); 4164 __ Ret();
3959 4165
3960 __ bind(&miss); 4166 __ bind(&miss);
3961 GenerateMiss(masm); 4167 GenerateMiss(masm);
3962 } 4168 }
3963 4169
3964 4170
3965 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) { 4171 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
3966 Label miss; 4172 Label miss;
3967 __ and_(r2, r1, Operand(r0)); 4173 __ and_(r5, r4, r3);
3968 __ JumpIfSmi(r2, &miss); 4174 __ JumpIfSmi(r5, &miss);
3969 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 4175 __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
3970 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 4176 __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset));
3971 __ cmp(r2, Operand(known_map_)); 4177 __ Cmpi(r5, Operand(known_map_), r0);
3972 __ b(ne, &miss); 4178 __ bne(&miss);
3973 __ cmp(r3, Operand(known_map_)); 4179 __ Cmpi(r6, Operand(known_map_), r0);
3974 __ b(ne, &miss); 4180 __ bne(&miss);
3975 4181
3976 __ sub(r0, r0, Operand(r1)); 4182 __ sub(r3, r3, r4);
3977 __ Ret(); 4183 __ Ret();
3978 4184
3979 __ bind(&miss); 4185 __ bind(&miss);
3980 GenerateMiss(masm); 4186 GenerateMiss(masm);
3981 } 4187 }
3982 4188
3983 4189
3984 4190
3985 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { 4191 void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
3986 { 4192 {
3987 // Call the runtime system in a fresh internal frame. 4193 // Call the runtime system in a fresh internal frame.
3988 ExternalReference miss = 4194 ExternalReference miss =
3989 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate()); 4195 ExternalReference(IC_Utility(IC::kCompareIC_Miss), isolate());
3990 4196
3991 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 4197 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
3992 __ Push(r1, r0); 4198 __ Push(r4, r3);
3993 __ Push(lr, r1, r0); 4199 __ mflr(r0);
3994 __ mov(ip, Operand(Smi::FromInt(op_))); 4200 __ Push(r0, r4, r3);
4201 __ LoadSmiLiteral(ip, Smi::FromInt(op_));
3995 __ push(ip); 4202 __ push(ip);
3996 __ CallExternalReference(miss, 3); 4203 __ CallExternalReference(miss, 3);
3997 // Compute the entry point of the rewritten stub. 4204 // Compute the entry point of the rewritten stub.
3998 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); 4205 __ addi(r5, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
3999 // Restore registers. 4206 // Restore registers.
4000 __ pop(lr); 4207 __ pop(r0);
4001 __ Pop(r1, r0); 4208 __ mtlr(r0);
4209 __ Pop(r4, r3);
4002 } 4210 }
4003 4211
4004 __ Jump(r2); 4212 __ Jump(r5);
4005 } 4213 }
4006 4214
4007 4215
4216 // This stub is paired with DirectCEntryStub::GenerateCall
4008 void DirectCEntryStub::Generate(MacroAssembler* masm) { 4217 void DirectCEntryStub::Generate(MacroAssembler* masm) {
4009 // Place the return address on the stack, making the call 4218 // Place the return address on the stack, making the call
4010 // GC safe. The RegExp backend also relies on this. 4219 // GC safe. The RegExp backend also relies on this.
4011 __ str(lr, MemOperand(sp, 0)); 4220 __ mflr(r0);
4012 __ blx(ip); // Call the C++ function. 4221 __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
4013 __ VFPEnsureFPSCRState(r2); 4222 __ Call(ip); // Call the C++ function.
4014 __ ldr(pc, MemOperand(sp, 0)); 4223 __ LoadP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
4224 __ mtlr(r0);
4225 __ blr();
4015 } 4226 }
4016 4227
4017 4228
4018 void DirectCEntryStub::GenerateCall(MacroAssembler* masm, 4229 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
4019 Register target) { 4230 Register target) {
4231 #if ABI_USES_FUNCTION_DESCRIPTORS && !defined(USE_SIMULATOR)
4232 // Native AIX/PPC64 Linux use a function descriptor.
4233 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(target, kPointerSize));
4234 __ LoadP(ip, MemOperand(target, 0)); // Instruction address
4235 #else
4236 // ip needs to be set for DirectCEentryStub::Generate, and also
4237 // for ABI_TOC_ADDRESSABILITY_VIA_IP.
4238 __ Move(ip, target);
4239 #endif
4240
4020 intptr_t code = 4241 intptr_t code =
4021 reinterpret_cast<intptr_t>(GetCode().location()); 4242 reinterpret_cast<intptr_t>(GetCode().location());
4022 __ Move(ip, target); 4243 __ mov(r0, Operand(code, RelocInfo::CODE_TARGET));
4023 __ mov(lr, Operand(code, RelocInfo::CODE_TARGET)); 4244 __ Call(r0); // Call the stub.
4024 __ blx(lr); // Call the stub.
4025 } 4245 }
4026 4246
4027 4247
4028 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, 4248 void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
4029 Label* miss, 4249 Label* miss,
4030 Label* done, 4250 Label* done,
4031 Register receiver, 4251 Register receiver,
4032 Register properties, 4252 Register properties,
4033 Handle<Name> name, 4253 Handle<Name> name,
4034 Register scratch0) { 4254 Register scratch0) {
4035 ASSERT(name->IsUniqueName()); 4255 ASSERT(name->IsUniqueName());
4036 // If names of slots in range from 1 to kProbes - 1 for the hash value are 4256 // If names of slots in range from 1 to kProbes - 1 for the hash value are
4037 // not equal to the name and kProbes-th slot is not used (its name is the 4257 // not equal to the name and kProbes-th slot is not used (its name is the
4038 // undefined value), it guarantees the hash table doesn't contain the 4258 // undefined value), it guarantees the hash table doesn't contain the
4039 // property. It's true even if some slots represent deleted properties 4259 // property. It's true even if some slots represent deleted properties
4040 // (their names are the hole value). 4260 // (their names are the hole value).
4041 for (int i = 0; i < kInlinedProbes; i++) { 4261 for (int i = 0; i < kInlinedProbes; i++) {
4042 // scratch0 points to properties hash. 4262 // scratch0 points to properties hash.
4043 // Compute the masked index: (hash + i + i * i) & mask. 4263 // Compute the masked index: (hash + i + i * i) & mask.
4044 Register index = scratch0; 4264 Register index = scratch0;
4045 // Capacity is smi 2^n. 4265 // Capacity is smi 2^n.
4046 __ ldr(index, FieldMemOperand(properties, kCapacityOffset)); 4266 __ LoadP(index, FieldMemOperand(properties, kCapacityOffset));
4047 __ sub(index, index, Operand(1)); 4267 __ subi(index, index, Operand(1));
4048 __ and_(index, index, Operand( 4268 __ LoadSmiLiteral(ip, Smi::FromInt(name->Hash() +
4049 Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i)))); 4269 NameDictionary::GetProbeOffset(i)));
4270 __ and_(index, index, ip);
4050 4271
4051 // Scale the index by multiplying by the entry size. 4272 // Scale the index by multiplying by the entry size.
4052 ASSERT(NameDictionary::kEntrySize == 3); 4273 ASSERT(NameDictionary::kEntrySize == 3);
4053 __ add(index, index, Operand(index, LSL, 1)); // index *= 3. 4274 __ ShiftLeftImm(ip, index, Operand(1));
4275 __ add(index, index, ip); // index *= 3.
4054 4276
4055 Register entity_name = scratch0; 4277 Register entity_name = scratch0;
4056 // Having undefined at this place means the name is not contained. 4278 // Having undefined at this place means the name is not contained.
4057 ASSERT_EQ(kSmiTagSize, 1);
4058 Register tmp = properties; 4279 Register tmp = properties;
4059 __ add(tmp, properties, Operand(index, LSL, 1)); 4280 __ SmiToPtrArrayOffset(ip, index);
4060 __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); 4281 __ add(tmp, properties, ip);
4282 __ LoadP(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
4061 4283
4062 ASSERT(!tmp.is(entity_name)); 4284 ASSERT(!tmp.is(entity_name));
4063 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); 4285 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
4064 __ cmp(entity_name, tmp); 4286 __ cmp(entity_name, tmp);
4065 __ b(eq, done); 4287 __ beq(done);
4066 4288
4067 // Load the hole ready for use below: 4289 // Load the hole ready for use below:
4068 __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex); 4290 __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
4069 4291
4070 // Stop if found the property. 4292 // Stop if found the property.
4071 __ cmp(entity_name, Operand(Handle<Name>(name))); 4293 __ Cmpi(entity_name, Operand(Handle<Name>(name)), r0);
4072 __ b(eq, miss); 4294 __ beq(miss);
4073 4295
4074 Label good; 4296 Label good;
4075 __ cmp(entity_name, tmp); 4297 __ cmp(entity_name, tmp);
4076 __ b(eq, &good); 4298 __ beq(&good);
4077 4299
4078 // Check if the entry name is not a unique name. 4300 // Check if the entry name is not a unique name.
4079 __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); 4301 __ LoadP(entity_name, FieldMemOperand(entity_name,
4080 __ ldrb(entity_name, 4302 HeapObject::kMapOffset));
4081 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); 4303 __ lbz(entity_name,
4304 FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
4082 __ JumpIfNotUniqueName(entity_name, miss); 4305 __ JumpIfNotUniqueName(entity_name, miss);
4083 __ bind(&good); 4306 __ bind(&good);
4084 4307
4085 // Restore the properties. 4308 // Restore the properties.
4086 __ ldr(properties, 4309 __ LoadP(properties,
4087 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 4310 FieldMemOperand(receiver, JSObject::kPropertiesOffset));
4088 } 4311 }
4089 4312
4090 const int spill_mask = 4313 const int spill_mask =
4091 (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() | 4314 (r0.bit() | r9.bit() | r8.bit() | r7.bit() | r6.bit() |
4092 r2.bit() | r1.bit() | r0.bit()); 4315 r5.bit() | r4.bit() | r3.bit());
4093 4316
4094 __ stm(db_w, sp, spill_mask); 4317 __ mflr(r0);
4095 __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 4318 __ MultiPush(spill_mask);
4096 __ mov(r1, Operand(Handle<Name>(name))); 4319
4320 __ LoadP(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
4321 __ mov(r4, Operand(Handle<Name>(name)));
4097 NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP); 4322 NameDictionaryLookupStub stub(masm->isolate(), NEGATIVE_LOOKUP);
4098 __ CallStub(&stub); 4323 __ CallStub(&stub);
4099 __ cmp(r0, Operand::Zero()); 4324 __ cmpi(r3, Operand::Zero());
4100 __ ldm(ia_w, sp, spill_mask);
4101 4325
4102 __ b(eq, done); 4326 __ MultiPop(spill_mask); // MultiPop does not touch condition flags
4103 __ b(ne, miss); 4327 __ mtlr(r0);
4328
4329 __ beq(done);
4330 __ bne(miss);
4104 } 4331 }
4105 4332
4106 4333
4107 // Probe the name dictionary in the |elements| register. Jump to the 4334 // Probe the name dictionary in the |elements| register. Jump to the
4108 // |done| label if a property with the given name is found. Jump to 4335 // |done| label if a property with the given name is found. Jump to
4109 // the |miss| label otherwise. 4336 // the |miss| label otherwise.
4110 // If lookup was successful |scratch2| will be equal to elements + 4 * index. 4337 // If lookup was successful |scratch2| will be equal to elements + 4 * index.
4111 void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, 4338 void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
4112 Label* miss, 4339 Label* miss,
4113 Label* done, 4340 Label* done,
4114 Register elements, 4341 Register elements,
4115 Register name, 4342 Register name,
4116 Register scratch1, 4343 Register scratch1,
4117 Register scratch2) { 4344 Register scratch2) {
4118 ASSERT(!elements.is(scratch1)); 4345 ASSERT(!elements.is(scratch1));
4119 ASSERT(!elements.is(scratch2)); 4346 ASSERT(!elements.is(scratch2));
4120 ASSERT(!name.is(scratch1)); 4347 ASSERT(!name.is(scratch1));
4121 ASSERT(!name.is(scratch2)); 4348 ASSERT(!name.is(scratch2));
4122 4349
4123 __ AssertName(name); 4350 __ AssertName(name);
4124 4351
4125 // Compute the capacity mask. 4352 // Compute the capacity mask.
4126 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); 4353 __ LoadP(scratch1, FieldMemOperand(elements, kCapacityOffset));
4127 __ SmiUntag(scratch1); 4354 __ SmiUntag(scratch1); // convert smi to int
4128 __ sub(scratch1, scratch1, Operand(1)); 4355 __ subi(scratch1, scratch1, Operand(1));
4129 4356
4130 // Generate an unrolled loop that performs a few probes before 4357 // Generate an unrolled loop that performs a few probes before
4131 // giving up. Measurements done on Gmail indicate that 2 probes 4358 // giving up. Measurements done on Gmail indicate that 2 probes
4132 // cover ~93% of loads from dictionaries. 4359 // cover ~93% of loads from dictionaries.
4133 for (int i = 0; i < kInlinedProbes; i++) { 4360 for (int i = 0; i < kInlinedProbes; i++) {
4134 // Compute the masked index: (hash + i + i * i) & mask. 4361 // Compute the masked index: (hash + i + i * i) & mask.
4135 __ ldr(scratch2, FieldMemOperand(name, Name::kHashFieldOffset)); 4362 __ lwz(scratch2, FieldMemOperand(name, Name::kHashFieldOffset));
4136 if (i > 0) { 4363 if (i > 0) {
4137 // Add the probe offset (i + i * i) left shifted to avoid right shifting 4364 // Add the probe offset (i + i * i) left shifted to avoid right shifting
4138 // the hash in a separate instruction. The value hash + i + i * i is right 4365 // the hash in a separate instruction. The value hash + i + i * i is right
4139 // shifted in the following and instruction. 4366 // shifted in the following and instruction.
4140 ASSERT(NameDictionary::GetProbeOffset(i) < 4367 ASSERT(NameDictionary::GetProbeOffset(i) <
4141 1 << (32 - Name::kHashFieldOffset)); 4368 1 << (32 - Name::kHashFieldOffset));
4142 __ add(scratch2, scratch2, Operand( 4369 __ addi(scratch2, scratch2, Operand(
4143 NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 4370 NameDictionary::GetProbeOffset(i) << Name::kHashShift));
4144 } 4371 }
4145 __ and_(scratch2, scratch1, Operand(scratch2, LSR, Name::kHashShift)); 4372 __ srwi(scratch2, scratch2, Operand(Name::kHashShift));
4373 __ and_(scratch2, scratch1, scratch2);
4146 4374
4147 // Scale the index by multiplying by the element size. 4375 // Scale the index by multiplying by the element size.
4148 ASSERT(NameDictionary::kEntrySize == 3); 4376 ASSERT(NameDictionary::kEntrySize == 3);
4149 // scratch2 = scratch2 * 3. 4377 // scratch2 = scratch2 * 3.
4150 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); 4378 __ ShiftLeftImm(ip, scratch2, Operand(1));
4379 __ add(scratch2, scratch2, ip);
4151 4380
4152 // Check if the key is identical to the name. 4381 // Check if the key is identical to the name.
4153 __ add(scratch2, elements, Operand(scratch2, LSL, 2)); 4382 __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2));
4154 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); 4383 __ add(scratch2, elements, ip);
4155 __ cmp(name, Operand(ip)); 4384 __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset));
4156 __ b(eq, done); 4385 __ cmp(name, ip);
4386 __ beq(done);
4157 } 4387 }
4158 4388
4159 const int spill_mask = 4389 const int spill_mask =
4160 (lr.bit() | r6.bit() | r5.bit() | r4.bit() | 4390 (r0.bit() | r9.bit() | r8.bit() | r7.bit() |
4161 r3.bit() | r2.bit() | r1.bit() | r0.bit()) & 4391 r6.bit() | r5.bit() | r4.bit() | r3.bit()) &
4162 ~(scratch1.bit() | scratch2.bit()); 4392 ~(scratch1.bit() | scratch2.bit());
4163 4393
4164 __ stm(db_w, sp, spill_mask); 4394 __ mflr(r0);
4165 if (name.is(r0)) { 4395 __ MultiPush(spill_mask);
4166 ASSERT(!elements.is(r1)); 4396 if (name.is(r3)) {
4167 __ Move(r1, name); 4397 ASSERT(!elements.is(r4));
4168 __ Move(r0, elements); 4398 __ mr(r4, name);
4399 __ mr(r3, elements);
4169 } else { 4400 } else {
4170 __ Move(r0, elements); 4401 __ mr(r3, elements);
4171 __ Move(r1, name); 4402 __ mr(r4, name);
4172 } 4403 }
4173 NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP); 4404 NameDictionaryLookupStub stub(masm->isolate(), POSITIVE_LOOKUP);
4174 __ CallStub(&stub); 4405 __ CallStub(&stub);
4175 __ cmp(r0, Operand::Zero()); 4406 __ cmpi(r3, Operand::Zero());
4176 __ mov(scratch2, Operand(r2)); 4407 __ mr(scratch2, r5);
4177 __ ldm(ia_w, sp, spill_mask); 4408 __ MultiPop(spill_mask);
4409 __ mtlr(r0);
4178 4410
4179 __ b(ne, done); 4411 __ bne(done);
4180 __ b(eq, miss); 4412 __ beq(miss);
4181 } 4413 }
4182 4414
4183 4415
4184 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 4416 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
4185 // This stub overrides SometimesSetsUpAFrame() to return false. That means 4417 // This stub overrides SometimesSetsUpAFrame() to return false. That means
4186 // we cannot call anything that could cause a GC from this stub. 4418 // we cannot call anything that could cause a GC from this stub.
4187 // Registers: 4419 // Registers:
4188 // result: NameDictionary to probe 4420 // result: NameDictionary to probe
4189 // r1: key 4421 // r4: key
4190 // dictionary: NameDictionary to probe. 4422 // dictionary: NameDictionary to probe.
4191 // index: will hold an index of entry if lookup is successful. 4423 // index: will hold an index of entry if lookup is successful.
4192 // might alias with result_. 4424 // might alias with result_.
4193 // Returns: 4425 // Returns:
4194 // result_ is zero if lookup failed, non zero otherwise. 4426 // result_ is zero if lookup failed, non zero otherwise.
4195 4427
4196 Register result = r0; 4428 Register result = r3;
4197 Register dictionary = r0; 4429 Register dictionary = r3;
4198 Register key = r1; 4430 Register key = r4;
4199 Register index = r2; 4431 Register index = r5;
4200 Register mask = r3; 4432 Register mask = r6;
4201 Register hash = r4; 4433 Register hash = r7;
4202 Register undefined = r5; 4434 Register undefined = r8;
4203 Register entry_key = r6; 4435 Register entry_key = r9;
4436 Register scratch = r9;
4204 4437
4205 Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 4438 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
4206 4439
4207 __ ldr(mask, FieldMemOperand(dictionary, kCapacityOffset)); 4440 __ LoadP(mask, FieldMemOperand(dictionary, kCapacityOffset));
4208 __ SmiUntag(mask); 4441 __ SmiUntag(mask);
4209 __ sub(mask, mask, Operand(1)); 4442 __ subi(mask, mask, Operand(1));
4210 4443
4211 __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 4444 __ lwz(hash, FieldMemOperand(key, Name::kHashFieldOffset));
4212 4445
4213 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); 4446 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
4214 4447
4215 for (int i = kInlinedProbes; i < kTotalProbes; i++) { 4448 for (int i = kInlinedProbes; i < kTotalProbes; i++) {
4216 // Compute the masked index: (hash + i + i * i) & mask. 4449 // Compute the masked index: (hash + i + i * i) & mask.
4217 // Capacity is smi 2^n. 4450 // Capacity is smi 2^n.
4218 if (i > 0) { 4451 if (i > 0) {
4219 // Add the probe offset (i + i * i) left shifted to avoid right shifting 4452 // Add the probe offset (i + i * i) left shifted to avoid right shifting
4220 // the hash in a separate instruction. The value hash + i + i * i is right 4453 // the hash in a separate instruction. The value hash + i + i * i is right
4221 // shifted in the following and instruction. 4454 // shifted in the following and instruction.
4222 ASSERT(NameDictionary::GetProbeOffset(i) < 4455 ASSERT(NameDictionary::GetProbeOffset(i) <
4223 1 << (32 - Name::kHashFieldOffset)); 4456 1 << (32 - Name::kHashFieldOffset));
4224 __ add(index, hash, Operand( 4457 __ addi(index, hash, Operand(
4225 NameDictionary::GetProbeOffset(i) << Name::kHashShift)); 4458 NameDictionary::GetProbeOffset(i) << Name::kHashShift));
4226 } else { 4459 } else {
4227 __ mov(index, Operand(hash)); 4460 __ mr(index, hash);
4228 } 4461 }
4229 __ and_(index, mask, Operand(index, LSR, Name::kHashShift)); 4462 __ srwi(r0, index, Operand(Name::kHashShift));
4463 __ and_(index, mask, r0);
4230 4464
4231 // Scale the index by multiplying by the entry size. 4465 // Scale the index by multiplying by the entry size.
4232 ASSERT(NameDictionary::kEntrySize == 3); 4466 ASSERT(NameDictionary::kEntrySize == 3);
4233 __ add(index, index, Operand(index, LSL, 1)); // index *= 3. 4467 __ ShiftLeftImm(scratch, index, Operand(1));
4468 __ add(index, index, scratch); // index *= 3.
4234 4469
4235 ASSERT_EQ(kSmiTagSize, 1); 4470 ASSERT_EQ(kSmiTagSize, 1);
4236 __ add(index, dictionary, Operand(index, LSL, 2)); 4471 __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2));
4237 __ ldr(entry_key, FieldMemOperand(index, kElementsStartOffset)); 4472 __ add(index, dictionary, scratch);
4473 __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset));
4238 4474
4239 // Having undefined at this place means the name is not contained. 4475 // Having undefined at this place means the name is not contained.
4240 __ cmp(entry_key, Operand(undefined)); 4476 __ cmp(entry_key, undefined);
4241 __ b(eq, &not_in_dictionary); 4477 __ beq(&not_in_dictionary);
4242 4478
4243 // Stop if found the property. 4479 // Stop if found the property.
4244 __ cmp(entry_key, Operand(key)); 4480 __ cmp(entry_key, key);
4245 __ b(eq, &in_dictionary); 4481 __ beq(&in_dictionary);
4246 4482
4247 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { 4483 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
4248 // Check if the entry name is not a unique name. 4484 // Check if the entry name is not a unique name.
4249 __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset)); 4485 __ LoadP(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
4250 __ ldrb(entry_key, 4486 __ lbz(entry_key,
4251 FieldMemOperand(entry_key, Map::kInstanceTypeOffset)); 4487 FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
4252 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary); 4488 __ JumpIfNotUniqueName(entry_key, &maybe_in_dictionary);
4253 } 4489 }
4254 } 4490 }
4255 4491
4256 __ bind(&maybe_in_dictionary); 4492 __ bind(&maybe_in_dictionary);
4257 // If we are doing negative lookup then probing failure should be 4493 // If we are doing negative lookup then probing failure should be
4258 // treated as a lookup success. For positive lookup probing failure 4494 // treated as a lookup success. For positive lookup probing failure
4259 // should be treated as lookup failure. 4495 // should be treated as lookup failure.
4260 if (mode_ == POSITIVE_LOOKUP) { 4496 if (mode_ == POSITIVE_LOOKUP) {
4261 __ mov(result, Operand::Zero()); 4497 __ li(result, Operand::Zero());
4262 __ Ret(); 4498 __ Ret();
4263 } 4499 }
4264 4500
4265 __ bind(&in_dictionary); 4501 __ bind(&in_dictionary);
4266 __ mov(result, Operand(1)); 4502 __ li(result, Operand(1));
4267 __ Ret(); 4503 __ Ret();
4268 4504
4269 __ bind(&not_in_dictionary); 4505 __ bind(&not_in_dictionary);
4270 __ mov(result, Operand::Zero()); 4506 __ li(result, Operand::Zero());
4271 __ Ret(); 4507 __ Ret();
4272 } 4508 }
4273 4509
4274 4510
4275 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 4511 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
4276 Isolate* isolate) { 4512 Isolate* isolate) {
4277 StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs); 4513 StoreBufferOverflowStub stub1(isolate, kDontSaveFPRegs);
4278 stub1.GetCode(); 4514 stub1.GetCode();
4279 // Hydrogen code stubs need stub2 at snapshot time. 4515 // Hydrogen code stubs need stub2 at snapshot time.
4280 StoreBufferOverflowStub stub2(isolate, kSaveFPRegs); 4516 StoreBufferOverflowStub stub2(isolate, kSaveFPRegs);
4281 stub2.GetCode(); 4517 stub2.GetCode();
4282 } 4518 }
4283 4519
4284 4520
4285 // Takes the input in 3 registers: address_ value_ and object_. A pointer to 4521 // Takes the input in 3 registers: address_ value_ and object_. A pointer to
4286 // the value has just been written into the object, now this stub makes sure 4522 // the value has just been written into the object, now this stub makes sure
4287 // we keep the GC informed. The word in the object where the value has been 4523 // we keep the GC informed. The word in the object where the value has been
4288 // written is in the address register. 4524 // written is in the address register.
4289 void RecordWriteStub::Generate(MacroAssembler* masm) { 4525 void RecordWriteStub::Generate(MacroAssembler* masm) {
4290 Label skip_to_incremental_noncompacting; 4526 Label skip_to_incremental_noncompacting;
4291 Label skip_to_incremental_compacting; 4527 Label skip_to_incremental_compacting;
4292 4528
4293 // The first two instructions are generated with labels so as to get the 4529 // The first two branch instructions are generated with labels so as to
4294 // offset fixed up correctly by the bind(Label*) call. We patch it back and 4530 // get the offset fixed up correctly by the bind(Label*) call. We patch
4295 // forth between a compare instructions (a nop in this position) and the 4531 // it back and forth between branch condition True and False
4296 // real branch when we start and stop incremental heap marking. 4532 // when we start and stop incremental heap marking.
4297 // See RecordWriteStub::Patch for details. 4533 // See RecordWriteStub::Patch for details.
4298 { 4534
4299 // Block literal pool emission, as the position of these two instructions 4535 // Clear the bit, branch on True for NOP action initially
4300 // is assumed by the patching code. 4536 __ crclr(Assembler::encode_crbit(cr2, CR_LT));
4301 Assembler::BlockConstPoolScope block_const_pool(masm); 4537 __ blt(&skip_to_incremental_noncompacting, cr2);
4302 __ b(&skip_to_incremental_noncompacting); 4538 __ blt(&skip_to_incremental_compacting, cr2);
4303 __ b(&skip_to_incremental_compacting);
4304 }
4305 4539
4306 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { 4540 if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
4307 __ RememberedSetHelper(object_, 4541 __ RememberedSetHelper(object_,
4308 address_, 4542 address_,
4309 value_, 4543 value_,
4310 save_fp_regs_mode_, 4544 save_fp_regs_mode_,
4311 MacroAssembler::kReturnAtEnd); 4545 MacroAssembler::kReturnAtEnd);
4312 } 4546 }
4313 __ Ret(); 4547 __ Ret();
4314 4548
4315 __ bind(&skip_to_incremental_noncompacting); 4549 __ bind(&skip_to_incremental_noncompacting);
4316 GenerateIncremental(masm, INCREMENTAL); 4550 GenerateIncremental(masm, INCREMENTAL);
4317 4551
4318 __ bind(&skip_to_incremental_compacting); 4552 __ bind(&skip_to_incremental_compacting);
4319 GenerateIncremental(masm, INCREMENTAL_COMPACTION); 4553 GenerateIncremental(masm, INCREMENTAL_COMPACTION);
4320 4554
4321 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY. 4555 // Initial mode of the stub is expected to be STORE_BUFFER_ONLY.
4322 // Will be checked in IncrementalMarking::ActivateGeneratedStub. 4556 // Will be checked in IncrementalMarking::ActivateGeneratedStub.
4323 ASSERT(Assembler::GetBranchOffset(masm->instr_at(0)) < (1 << 12)); 4557 // patching not required on PPC as the initial path is effectively NOP
4324 ASSERT(Assembler::GetBranchOffset(masm->instr_at(4)) < (1 << 12));
4325 PatchBranchIntoNop(masm, 0);
4326 PatchBranchIntoNop(masm, Assembler::kInstrSize);
4327 } 4558 }
4328 4559
4329 4560
4330 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) { 4561 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
4331 regs_.Save(masm); 4562 regs_.Save(masm);
4332 4563
4333 if (remembered_set_action_ == EMIT_REMEMBERED_SET) { 4564 if (remembered_set_action_ == EMIT_REMEMBERED_SET) {
4334 Label dont_need_remembered_set; 4565 Label dont_need_remembered_set;
4335 4566
4336 __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); 4567 __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0));
4337 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value. 4568 __ JumpIfNotInNewSpace(regs_.scratch0(), // Value.
4338 regs_.scratch0(), 4569 regs_.scratch0(),
4339 &dont_need_remembered_set); 4570 &dont_need_remembered_set);
4340 4571
4341 __ CheckPageFlag(regs_.object(), 4572 __ CheckPageFlag(regs_.object(),
4342 regs_.scratch0(), 4573 regs_.scratch0(),
4343 1 << MemoryChunk::SCAN_ON_SCAVENGE, 4574 1 << MemoryChunk::SCAN_ON_SCAVENGE,
4344 ne, 4575 ne,
4345 &dont_need_remembered_set); 4576 &dont_need_remembered_set);
4346 4577
(...skipping 18 matching lines...) Expand all
4365 regs_.Restore(masm); 4596 regs_.Restore(masm);
4366 __ Ret(); 4597 __ Ret();
4367 } 4598 }
4368 4599
4369 4600
4370 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) { 4601 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm) {
4371 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); 4602 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_);
4372 int argument_count = 3; 4603 int argument_count = 3;
4373 __ PrepareCallCFunction(argument_count, regs_.scratch0()); 4604 __ PrepareCallCFunction(argument_count, regs_.scratch0());
4374 Register address = 4605 Register address =
4375 r0.is(regs_.address()) ? regs_.scratch0() : regs_.address(); 4606 r3.is(regs_.address()) ? regs_.scratch0() : regs_.address();
4376 ASSERT(!address.is(regs_.object())); 4607 ASSERT(!address.is(regs_.object()));
4377 ASSERT(!address.is(r0)); 4608 ASSERT(!address.is(r3));
4378 __ Move(address, regs_.address()); 4609 __ mr(address, regs_.address());
4379 __ Move(r0, regs_.object()); 4610 __ mr(r3, regs_.object());
4380 __ Move(r1, address); 4611 __ mr(r4, address);
4381 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); 4612 __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
4382 4613
4383 AllowExternalCallThatCantCauseGC scope(masm); 4614 AllowExternalCallThatCantCauseGC scope(masm);
4384 __ CallCFunction( 4615 __ CallCFunction(
4385 ExternalReference::incremental_marking_record_write_function(isolate()), 4616 ExternalReference::incremental_marking_record_write_function(isolate()),
4386 argument_count); 4617 argument_count);
4387 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_); 4618 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_);
4388 } 4619 }
4389 4620
4390 4621
4391 void RecordWriteStub::CheckNeedsToInformIncrementalMarker( 4622 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
4392 MacroAssembler* masm, 4623 MacroAssembler* masm,
4393 OnNoNeedToInformIncrementalMarker on_no_need, 4624 OnNoNeedToInformIncrementalMarker on_no_need,
4394 Mode mode) { 4625 Mode mode) {
4395 Label on_black; 4626 Label on_black;
4396 Label need_incremental; 4627 Label need_incremental;
4397 Label need_incremental_pop_scratch; 4628 Label need_incremental_pop_scratch;
4398 4629
4399 __ and_(regs_.scratch0(), regs_.object(), Operand(~Page::kPageAlignmentMask)); 4630 ASSERT((~Page::kPageAlignmentMask & 0xffff) == 0);
4400 __ ldr(regs_.scratch1(), 4631 __ lis(r0, Operand((~Page::kPageAlignmentMask >> 16)));
4632 __ and_(regs_.scratch0(), regs_.object(), r0);
4633 __ LoadP(regs_.scratch1(),
4401 MemOperand(regs_.scratch0(), 4634 MemOperand(regs_.scratch0(),
4402 MemoryChunk::kWriteBarrierCounterOffset)); 4635 MemoryChunk::kWriteBarrierCounterOffset));
4403 __ sub(regs_.scratch1(), regs_.scratch1(), Operand(1), SetCC); 4636 __ subi(regs_.scratch1(), regs_.scratch1(), Operand(1));
4404 __ str(regs_.scratch1(), 4637 __ StoreP(regs_.scratch1(),
4405 MemOperand(regs_.scratch0(), 4638 MemOperand(regs_.scratch0(),
4406 MemoryChunk::kWriteBarrierCounterOffset)); 4639 MemoryChunk::kWriteBarrierCounterOffset));
4407 __ b(mi, &need_incremental); 4640 __ cmpi(regs_.scratch1(), Operand::Zero()); // PPC, we could do better here
4641 __ blt(&need_incremental);
4408 4642
4409 // Let's look at the color of the object: If it is not black we don't have 4643 // Let's look at the color of the object: If it is not black we don't have
4410 // to inform the incremental marker. 4644 // to inform the incremental marker.
4411 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black); 4645 __ JumpIfBlack(regs_.object(), regs_.scratch0(), regs_.scratch1(), &on_black);
4412 4646
4413 regs_.Restore(masm); 4647 regs_.Restore(masm);
4414 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) { 4648 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
4415 __ RememberedSetHelper(object_, 4649 __ RememberedSetHelper(object_,
4416 address_, 4650 address_,
4417 value_, 4651 value_,
4418 save_fp_regs_mode_, 4652 save_fp_regs_mode_,
4419 MacroAssembler::kReturnAtEnd); 4653 MacroAssembler::kReturnAtEnd);
4420 } else { 4654 } else {
4421 __ Ret(); 4655 __ Ret();
4422 } 4656 }
4423 4657
4424 __ bind(&on_black); 4658 __ bind(&on_black);
4425 4659
4426 // Get the value from the slot. 4660 // Get the value from the slot.
4427 __ ldr(regs_.scratch0(), MemOperand(regs_.address(), 0)); 4661 __ LoadP(regs_.scratch0(), MemOperand(regs_.address(), 0));
4428 4662
4429 if (mode == INCREMENTAL_COMPACTION) { 4663 if (mode == INCREMENTAL_COMPACTION) {
4430 Label ensure_not_white; 4664 Label ensure_not_white;
4431 4665
4432 __ CheckPageFlag(regs_.scratch0(), // Contains value. 4666 __ CheckPageFlag(regs_.scratch0(), // Contains value.
4433 regs_.scratch1(), // Scratch. 4667 regs_.scratch1(), // Scratch.
4434 MemoryChunk::kEvacuationCandidateMask, 4668 MemoryChunk::kEvacuationCandidateMask,
4435 eq, 4669 eq,
4436 &ensure_not_white); 4670 &ensure_not_white);
4437 4671
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4469 __ Pop(regs_.object(), regs_.address()); 4703 __ Pop(regs_.object(), regs_.address());
4470 4704
4471 __ bind(&need_incremental); 4705 __ bind(&need_incremental);
4472 4706
4473 // Fall through when we need to inform the incremental marker. 4707 // Fall through when we need to inform the incremental marker.
4474 } 4708 }
4475 4709
4476 4710
4477 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { 4711 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
4478 // ----------- S t a t e ------------- 4712 // ----------- S t a t e -------------
4479 // -- r0 : element value to store 4713 // -- r3 : element value to store
4480 // -- r3 : element index as smi 4714 // -- r6 : element index as smi
4481 // -- sp[0] : array literal index in function as smi 4715 // -- sp[0] : array literal index in function as smi
4482 // -- sp[4] : array literal 4716 // -- sp[4] : array literal
4483 // clobbers r1, r2, r4 4717 // clobbers r3, r5, r7
4484 // ----------------------------------- 4718 // -----------------------------------
4485 4719
4486 Label element_done; 4720 Label element_done;
4487 Label double_elements; 4721 Label double_elements;
4488 Label smi_element; 4722 Label smi_element;
4489 Label slow_elements; 4723 Label slow_elements;
4490 Label fast_elements; 4724 Label fast_elements;
4491 4725
4492 // Get array literal index, array literal and its map. 4726 // Get array literal index, array literal and its map.
4493 __ ldr(r4, MemOperand(sp, 0 * kPointerSize)); 4727 __ LoadP(r7, MemOperand(sp, 0 * kPointerSize));
4494 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 4728 __ LoadP(r4, MemOperand(sp, 1 * kPointerSize));
4495 __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset)); 4729 __ LoadP(r5, FieldMemOperand(r4, JSObject::kMapOffset));
4496 4730
4497 __ CheckFastElements(r2, r5, &double_elements); 4731 __ CheckFastElements(r5, r8, &double_elements);
4498 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS 4732 // FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS
4499 __ JumpIfSmi(r0, &smi_element); 4733 __ JumpIfSmi(r3, &smi_element);
4500 __ CheckFastSmiElements(r2, r5, &fast_elements); 4734 __ CheckFastSmiElements(r5, r8, &fast_elements);
4501 4735
4502 // Store into the array literal requires a elements transition. Call into 4736 // Store into the array literal requires a elements transition. Call into
4503 // the runtime. 4737 // the runtime.
4504 __ bind(&slow_elements); 4738 __ bind(&slow_elements);
4505 // call. 4739 // call.
4506 __ Push(r1, r3, r0); 4740 __ Push(r4, r6, r3);
4507 __ ldr(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4741 __ LoadP(r8, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4508 __ ldr(r5, FieldMemOperand(r5, JSFunction::kLiteralsOffset)); 4742 __ LoadP(r8, FieldMemOperand(r8, JSFunction::kLiteralsOffset));
4509 __ Push(r5, r4); 4743 __ Push(r8, r7);
4510 __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); 4744 __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
4511 4745
4512 // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object. 4746 // Array literal has ElementsKind of FAST_*_ELEMENTS and value is an object.
4513 __ bind(&fast_elements); 4747 __ bind(&fast_elements);
4514 __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); 4748 __ LoadP(r8, FieldMemOperand(r4, JSObject::kElementsOffset));
4515 __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3)); 4749 __ SmiToPtrArrayOffset(r9, r6);
4516 __ add(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4750 __ add(r9, r8, r9);
4517 __ str(r0, MemOperand(r6, 0)); 4751 #if V8_TARGET_ARCH_PPC64
4752 // add due to offset alignment requirements of StorePU
4753 __ addi(r9, r9, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4754 __ StoreP(r3, MemOperand(r9));
4755 #else
4756 __ StorePU(r3, MemOperand(r9, FixedArray::kHeaderSize - kHeapObjectTag));
4757 #endif
4518 // Update the write barrier for the array store. 4758 // Update the write barrier for the array store.
4519 __ RecordWrite(r5, r6, r0, kLRHasNotBeenSaved, kDontSaveFPRegs, 4759 __ RecordWrite(r8, r9, r3, kLRHasNotBeenSaved, kDontSaveFPRegs,
4520 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 4760 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
4521 __ Ret(); 4761 __ Ret();
4522 4762
4523 // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS, 4763 // Array literal has ElementsKind of FAST_*_SMI_ELEMENTS or FAST_*_ELEMENTS,
4524 // and value is Smi. 4764 // and value is Smi.
4525 __ bind(&smi_element); 4765 __ bind(&smi_element);
4526 __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); 4766 __ LoadP(r8, FieldMemOperand(r4, JSObject::kElementsOffset));
4527 __ add(r6, r5, Operand::PointerOffsetFromSmiKey(r3)); 4767 __ SmiToPtrArrayOffset(r9, r6);
4528 __ str(r0, FieldMemOperand(r6, FixedArray::kHeaderSize)); 4768 __ add(r9, r8, r9);
4769 __ StoreP(r3, FieldMemOperand(r9, FixedArray::kHeaderSize), r0);
4529 __ Ret(); 4770 __ Ret();
4530 4771
4531 // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. 4772 // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
4532 __ bind(&double_elements); 4773 __ bind(&double_elements);
4533 __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); 4774 __ LoadP(r8, FieldMemOperand(r4, JSObject::kElementsOffset));
4534 __ StoreNumberToDoubleElements(r0, r3, r5, r6, d0, &slow_elements); 4775 __ StoreNumberToDoubleElements(r3, r6, r8, r9, d0, &slow_elements);
4535 __ Ret(); 4776 __ Ret();
4536 } 4777 }
4537 4778
4538 4779
4539 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) { 4780 void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
4540 CEntryStub ces(isolate(), 1, kSaveFPRegs); 4781 CEntryStub ces(isolate(), 1, kSaveFPRegs);
4541 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET); 4782 __ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
4542 int parameter_count_offset = 4783 int parameter_count_offset =
4543 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; 4784 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
4544 __ ldr(r1, MemOperand(fp, parameter_count_offset)); 4785 __ LoadP(r4, MemOperand(fp, parameter_count_offset));
4545 if (function_mode_ == JS_FUNCTION_STUB_MODE) { 4786 if (function_mode_ == JS_FUNCTION_STUB_MODE) {
4546 __ add(r1, r1, Operand(1)); 4787 __ addi(r4, r4, Operand(1));
4547 } 4788 }
4548 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); 4789 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
4549 __ mov(r1, Operand(r1, LSL, kPointerSizeLog2)); 4790 __ slwi(r4, r4, Operand(kPointerSizeLog2));
4550 __ add(sp, sp, r1); 4791 __ add(sp, sp, r4);
4551 __ Ret(); 4792 __ Ret();
4552 } 4793 }
4553 4794
4554 4795
4555 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 4796 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
4556 if (masm->isolate()->function_entry_hook() != NULL) { 4797 if (masm->isolate()->function_entry_hook() != NULL) {
4798 PredictableCodeSizeScope predictable(masm,
4799 #if V8_TARGET_ARCH_PPC64
4800 12 * Assembler::kInstrSize);
4801 #else
4802 9 * Assembler::kInstrSize);
4803 #endif
4557 ProfileEntryHookStub stub(masm->isolate()); 4804 ProfileEntryHookStub stub(masm->isolate());
4558 int code_size = masm->CallStubSize(&stub) + 2 * Assembler::kInstrSize; 4805 __ mflr(r0);
4559 PredictableCodeSizeScope predictable(masm, code_size); 4806 __ push(r0);
4560 __ push(lr);
4561 __ CallStub(&stub); 4807 __ CallStub(&stub);
4562 __ pop(lr); 4808 __ pop(r0);
4809 __ mtlr(r0);
4563 } 4810 }
4564 } 4811 }
4565 4812
4566 4813
4567 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { 4814 void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
4568 // The entry hook is a "push lr" instruction, followed by a call. 4815 // The entry hook is a "push lr" instruction, followed by a call.
4569 const int32_t kReturnAddressDistanceFromFunctionStart = 4816 const int32_t kReturnAddressDistanceFromFunctionStart =
4570 3 * Assembler::kInstrSize; 4817 Assembler::kCallTargetAddressOffset + 2 * Assembler::kInstrSize;
4571 4818
4572 // This should contain all kCallerSaved registers. 4819 // This should contain all kJSCallerSaved registers.
4573 const RegList kSavedRegs = 4820 const RegList kSavedRegs =
4574 1 << 0 | // r0 4821 kJSCallerSaved | // Caller saved registers.
4575 1 << 1 | // r1 4822 r15.bit(); // Saved stack pointer.
4576 1 << 2 | // r2 4823
4577 1 << 3 | // r3
4578 1 << 5 | // r5
4579 1 << 9; // r9
4580 // We also save lr, so the count here is one higher than the mask indicates. 4824 // We also save lr, so the count here is one higher than the mask indicates.
4581 const int32_t kNumSavedRegs = 7; 4825 const int32_t kNumSavedRegs = kNumJSCallerSaved + 2;
4582
4583 ASSERT((kCallerSaved & kSavedRegs) == kCallerSaved);
4584 4826
4585 // Save all caller-save registers as this may be called from anywhere. 4827 // Save all caller-save registers as this may be called from anywhere.
4586 __ stm(db_w, sp, kSavedRegs | lr.bit()); 4828 __ mflr(r0);
4829 __ MultiPush(kSavedRegs | r0.bit());
4587 4830
4588 // Compute the function's address for the first argument. 4831 // Compute the function's address for the first argument.
4589 __ sub(r0, lr, Operand(kReturnAddressDistanceFromFunctionStart)); 4832 __ mr(r3, r0);
4833 __ subi(r3, r3, Operand(kReturnAddressDistanceFromFunctionStart));
4590 4834
4591 // The caller's return address is above the saved temporaries. 4835 // The caller's return address is above the saved temporaries.
4592 // Grab that for the second argument to the hook. 4836 // Grab that for the second argument to the hook.
4593 __ add(r1, sp, Operand(kNumSavedRegs * kPointerSize)); 4837 __ addi(r4, sp, Operand(kNumSavedRegs * kPointerSize));
4594 4838
4595 // Align the stack if necessary. 4839 // Align the stack if necessary.
4596 int frame_alignment = masm->ActivationFrameAlignment(); 4840 int frame_alignment = masm->ActivationFrameAlignment();
4597 if (frame_alignment > kPointerSize) { 4841 if (frame_alignment > kPointerSize) {
4598 __ mov(r5, sp); 4842 __ mr(r15, sp);
4599 ASSERT(IsPowerOf2(frame_alignment)); 4843 ASSERT(IsPowerOf2(frame_alignment));
4600 __ and_(sp, sp, Operand(-frame_alignment)); 4844 __ ClearRightImm(sp, sp, Operand(WhichPowerOf2(frame_alignment)));
4601 } 4845 }
4602 4846
4603 #if V8_HOST_ARCH_ARM 4847 #if !defined(USE_SIMULATOR)
4604 int32_t entry_hook = 4848 uintptr_t entry_hook =
4605 reinterpret_cast<int32_t>(isolate()->function_entry_hook()); 4849 reinterpret_cast<uintptr_t>(isolate()->function_entry_hook());
4606 __ mov(ip, Operand(entry_hook)); 4850 __ mov(ip, Operand(entry_hook));
4851
4852 #if ABI_USES_FUNCTION_DESCRIPTORS
4853 // Function descriptor
4854 __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(ip, kPointerSize));
4855 __ LoadP(ip, MemOperand(ip, 0));
4856 #elif ABI_TOC_ADDRESSABILITY_VIA_IP
4857 // ip set above, so nothing to do.
4858 #endif
4859
4860 // PPC LINUX ABI:
4861 __ li(r0, Operand::Zero());
4862 __ StorePU(r0, MemOperand(sp, -kNumRequiredStackFrameSlots * kPointerSize));
4607 #else 4863 #else
4608 // Under the simulator we need to indirect the entry hook through a 4864 // Under the simulator we need to indirect the entry hook through a
4609 // trampoline function at a known address. 4865 // trampoline function at a known address.
4610 // It additionally takes an isolate as a third parameter 4866 // It additionally takes an isolate as a third parameter
4611 __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); 4867 __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
4612 4868
4613 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); 4869 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline));
4614 __ mov(ip, Operand(ExternalReference(&dispatcher, 4870 __ mov(ip, Operand(ExternalReference(&dispatcher,
4615 ExternalReference::BUILTIN_CALL, 4871 ExternalReference::BUILTIN_CALL,
4616 isolate()))); 4872 isolate())));
4617 #endif 4873 #endif
4618 __ Call(ip); 4874 __ Call(ip);
4619 4875
4876 #if !defined(USE_SIMULATOR)
4877 __ addi(sp, sp, Operand(kNumRequiredStackFrameSlots * kPointerSize));
4878 #endif
4879
4620 // Restore the stack pointer if needed. 4880 // Restore the stack pointer if needed.
4621 if (frame_alignment > kPointerSize) { 4881 if (frame_alignment > kPointerSize) {
4622 __ mov(sp, r5); 4882 __ mr(sp, r15);
4623 } 4883 }
4624 4884
4625 // Also pop pc to get Ret(0). 4885 // Also pop lr to get Ret(0).
4626 __ ldm(ia_w, sp, kSavedRegs | pc.bit()); 4886 __ MultiPop(kSavedRegs | r0.bit());
4887 __ mtlr(r0);
4888 __ Ret();
4627 } 4889 }
4628 4890
4629 4891
4630 template<class T> 4892 template<class T>
4631 static void CreateArrayDispatch(MacroAssembler* masm, 4893 static void CreateArrayDispatch(MacroAssembler* masm,
4632 AllocationSiteOverrideMode mode) { 4894 AllocationSiteOverrideMode mode) {
4633 if (mode == DISABLE_ALLOCATION_SITES) { 4895 if (mode == DISABLE_ALLOCATION_SITES) {
4634 T stub(masm->isolate(), GetInitialFastElementsKind(), mode); 4896 T stub(masm->isolate(), GetInitialFastElementsKind(), mode);
4635 __ TailCallStub(&stub); 4897 __ TailCallStub(&stub);
4636 } else if (mode == DONT_OVERRIDE) { 4898 } else if (mode == DONT_OVERRIDE) {
4637 int last_index = GetSequenceIndexFromFastElementsKind( 4899 int last_index = GetSequenceIndexFromFastElementsKind(
4638 TERMINAL_FAST_ELEMENTS_KIND); 4900 TERMINAL_FAST_ELEMENTS_KIND);
4639 for (int i = 0; i <= last_index; ++i) { 4901 for (int i = 0; i <= last_index; ++i) {
4640 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4902 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4641 __ cmp(r3, Operand(kind)); 4903 __ Cmpi(r6, Operand(kind), r0);
4642 T stub(masm->isolate(), kind); 4904 T stub(masm->isolate(), kind);
4643 __ TailCallStub(&stub, eq); 4905 __ TailCallStub(&stub, eq);
4644 } 4906 }
4645 4907
4646 // If we reached this point there is a problem. 4908 // If we reached this point there is a problem.
4647 __ Abort(kUnexpectedElementsKindInArrayConstructor); 4909 __ Abort(kUnexpectedElementsKindInArrayConstructor);
4648 } else { 4910 } else {
4649 UNREACHABLE(); 4911 UNREACHABLE();
4650 } 4912 }
4651 } 4913 }
4652 4914
4653 4915
4654 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, 4916 static void CreateArrayDispatchOneArgument(MacroAssembler* masm,
4655 AllocationSiteOverrideMode mode) { 4917 AllocationSiteOverrideMode mode) {
4656 // r2 - allocation site (if mode != DISABLE_ALLOCATION_SITES) 4918 // r5 - allocation site (if mode != DISABLE_ALLOCATION_SITES)
4657 // r3 - kind (if mode != DISABLE_ALLOCATION_SITES) 4919 // r6 - kind (if mode != DISABLE_ALLOCATION_SITES)
4658 // r0 - number of arguments 4920 // r3 - number of arguments
4659 // r1 - constructor? 4921 // r4 - constructor?
4660 // sp[0] - last argument 4922 // sp[0] - last argument
4661 Label normal_sequence; 4923 Label normal_sequence;
4662 if (mode == DONT_OVERRIDE) { 4924 if (mode == DONT_OVERRIDE) {
4663 ASSERT(FAST_SMI_ELEMENTS == 0); 4925 ASSERT(FAST_SMI_ELEMENTS == 0);
4664 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 4926 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
4665 ASSERT(FAST_ELEMENTS == 2); 4927 ASSERT(FAST_ELEMENTS == 2);
4666 ASSERT(FAST_HOLEY_ELEMENTS == 3); 4928 ASSERT(FAST_HOLEY_ELEMENTS == 3);
4667 ASSERT(FAST_DOUBLE_ELEMENTS == 4); 4929 ASSERT(FAST_DOUBLE_ELEMENTS == 4);
4668 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 4930 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
4669 4931
4670 // is the low bit set? If so, we are holey and that is good. 4932 // is the low bit set? If so, we are holey and that is good.
4671 __ tst(r3, Operand(1)); 4933 __ andi(r0, r6, Operand(1));
4672 __ b(ne, &normal_sequence); 4934 __ bne(&normal_sequence, cr0);
4673 } 4935 }
4674 4936
4675 // look at the first argument 4937 // look at the first argument
4676 __ ldr(r5, MemOperand(sp, 0)); 4938 __ LoadP(r8, MemOperand(sp, 0));
4677 __ cmp(r5, Operand::Zero()); 4939 __ cmpi(r8, Operand::Zero());
4678 __ b(eq, &normal_sequence); 4940 __ beq(&normal_sequence);
4679 4941
4680 if (mode == DISABLE_ALLOCATION_SITES) { 4942 if (mode == DISABLE_ALLOCATION_SITES) {
4681 ElementsKind initial = GetInitialFastElementsKind(); 4943 ElementsKind initial = GetInitialFastElementsKind();
4682 ElementsKind holey_initial = GetHoleyElementsKind(initial); 4944 ElementsKind holey_initial = GetHoleyElementsKind(initial);
4683 4945
4684 ArraySingleArgumentConstructorStub stub_holey(masm->isolate(), 4946 ArraySingleArgumentConstructorStub stub_holey(masm->isolate(),
4685 holey_initial, 4947 holey_initial,
4686 DISABLE_ALLOCATION_SITES); 4948 DISABLE_ALLOCATION_SITES);
4687 __ TailCallStub(&stub_holey); 4949 __ TailCallStub(&stub_holey);
4688 4950
4689 __ bind(&normal_sequence); 4951 __ bind(&normal_sequence);
4690 ArraySingleArgumentConstructorStub stub(masm->isolate(), 4952 ArraySingleArgumentConstructorStub stub(masm->isolate(),
4691 initial, 4953 initial,
4692 DISABLE_ALLOCATION_SITES); 4954 DISABLE_ALLOCATION_SITES);
4693 __ TailCallStub(&stub); 4955 __ TailCallStub(&stub);
4694 } else if (mode == DONT_OVERRIDE) { 4956 } else if (mode == DONT_OVERRIDE) {
4695 // We are going to create a holey array, but our kind is non-holey. 4957 // We are going to create a holey array, but our kind is non-holey.
4696 // Fix kind and retry (only if we have an allocation site in the slot). 4958 // Fix kind and retry (only if we have an allocation site in the slot).
4697 __ add(r3, r3, Operand(1)); 4959 __ addi(r6, r6, Operand(1));
4698 4960
4699 if (FLAG_debug_code) { 4961 if (FLAG_debug_code) {
4700 __ ldr(r5, FieldMemOperand(r2, 0)); 4962 __ LoadP(r8, FieldMemOperand(r5, 0));
4701 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); 4963 __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
4702 __ Assert(eq, kExpectedAllocationSite); 4964 __ Assert(eq, kExpectedAllocationSite);
4703 } 4965 }
4704 4966
4705 // Save the resulting elements kind in type info. We can't just store r3 4967 // Save the resulting elements kind in type info. We can't just store r6
4706 // in the AllocationSite::transition_info field because elements kind is 4968 // in the AllocationSite::transition_info field because elements kind is
4707 // restricted to a portion of the field...upper bits need to be left alone. 4969 // restricted to a portion of the field...upper bits need to be left alone.
4708 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 4970 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4709 __ ldr(r4, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset)); 4971 __ LoadP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset));
4710 __ add(r4, r4, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); 4972 __ AddSmiLiteral(r7, r7, Smi::FromInt(kFastElementsKindPackedToHoley), r0);
4711 __ str(r4, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset)); 4973 __ StoreP(r7, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset),
4974 r0);
4712 4975
4713 __ bind(&normal_sequence); 4976 __ bind(&normal_sequence);
4714 int last_index = GetSequenceIndexFromFastElementsKind( 4977 int last_index = GetSequenceIndexFromFastElementsKind(
4715 TERMINAL_FAST_ELEMENTS_KIND); 4978 TERMINAL_FAST_ELEMENTS_KIND);
4716 for (int i = 0; i <= last_index; ++i) { 4979 for (int i = 0; i <= last_index; ++i) {
4717 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 4980 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
4718 __ cmp(r3, Operand(kind)); 4981 __ mov(r0, Operand(kind));
4982 __ cmp(r6, r0);
4719 ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); 4983 ArraySingleArgumentConstructorStub stub(masm->isolate(), kind);
4720 __ TailCallStub(&stub, eq); 4984 __ TailCallStub(&stub, eq);
4721 } 4985 }
4722 4986
4723 // If we reached this point there is a problem. 4987 // If we reached this point there is a problem.
4724 __ Abort(kUnexpectedElementsKindInArrayConstructor); 4988 __ Abort(kUnexpectedElementsKindInArrayConstructor);
4725 } else { 4989 } else {
4726 UNREACHABLE(); 4990 UNREACHABLE();
4727 } 4991 }
4728 } 4992 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4767 stubh3.GetCode(); 5031 stubh3.GetCode();
4768 } 5032 }
4769 } 5033 }
4770 5034
4771 5035
4772 void ArrayConstructorStub::GenerateDispatchToArrayStub( 5036 void ArrayConstructorStub::GenerateDispatchToArrayStub(
4773 MacroAssembler* masm, 5037 MacroAssembler* masm,
4774 AllocationSiteOverrideMode mode) { 5038 AllocationSiteOverrideMode mode) {
4775 if (argument_count_ == ANY) { 5039 if (argument_count_ == ANY) {
4776 Label not_zero_case, not_one_case; 5040 Label not_zero_case, not_one_case;
4777 __ tst(r0, r0); 5041 __ cmpi(r3, Operand::Zero());
4778 __ b(ne, &not_zero_case); 5042 __ bne(&not_zero_case);
4779 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 5043 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4780 5044
4781 __ bind(&not_zero_case); 5045 __ bind(&not_zero_case);
4782 __ cmp(r0, Operand(1)); 5046 __ cmpi(r3, Operand(1));
4783 __ b(gt, &not_one_case); 5047 __ bgt(&not_one_case);
4784 CreateArrayDispatchOneArgument(masm, mode); 5048 CreateArrayDispatchOneArgument(masm, mode);
4785 5049
4786 __ bind(&not_one_case); 5050 __ bind(&not_one_case);
4787 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 5051 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4788 } else if (argument_count_ == NONE) { 5052 } else if (argument_count_ == NONE) {
4789 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); 5053 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
4790 } else if (argument_count_ == ONE) { 5054 } else if (argument_count_ == ONE) {
4791 CreateArrayDispatchOneArgument(masm, mode); 5055 CreateArrayDispatchOneArgument(masm, mode);
4792 } else if (argument_count_ == MORE_THAN_ONE) { 5056 } else if (argument_count_ == MORE_THAN_ONE) {
4793 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); 5057 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
4794 } else { 5058 } else {
4795 UNREACHABLE(); 5059 UNREACHABLE();
4796 } 5060 }
4797 } 5061 }
4798 5062
4799 5063
4800 void ArrayConstructorStub::Generate(MacroAssembler* masm) { 5064 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
4801 // ----------- S t a t e ------------- 5065 // ----------- S t a t e -------------
4802 // -- r0 : argc (only if argument_count_ == ANY) 5066 // -- r3 : argc (only if argument_count_ == ANY)
4803 // -- r1 : constructor 5067 // -- r4 : constructor
4804 // -- r2 : AllocationSite or undefined 5068 // -- r5 : AllocationSite or undefined
4805 // -- sp[0] : return address 5069 // -- sp[0] : return address
4806 // -- sp[4] : last argument 5070 // -- sp[4] : last argument
4807 // ----------------------------------- 5071 // -----------------------------------
4808 5072
4809 if (FLAG_debug_code) { 5073 if (FLAG_debug_code) {
4810 // The array construct code is only set for the global and natives 5074 // The array construct code is only set for the global and natives
4811 // builtin Array functions which always have maps. 5075 // builtin Array functions which always have maps.
4812 5076
4813 // Initial map for the builtin Array function should be a map. 5077 // Initial map for the builtin Array function should be a map.
4814 __ ldr(r4, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 5078 __ LoadP(r7, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
4815 // Will both indicate a NULL and a Smi. 5079 // Will both indicate a NULL and a Smi.
4816 __ tst(r4, Operand(kSmiTagMask)); 5080 __ TestIfSmi(r7, r0);
4817 __ Assert(ne, kUnexpectedInitialMapForArrayFunction); 5081 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0);
4818 __ CompareObjectType(r4, r4, r5, MAP_TYPE); 5082 __ CompareObjectType(r7, r7, r8, MAP_TYPE);
4819 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 5083 __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
4820 5084
4821 // We should either have undefined in r2 or a valid AllocationSite 5085 // We should either have undefined in r5 or a valid AllocationSite
4822 __ AssertUndefinedOrAllocationSite(r2, r4); 5086 __ AssertUndefinedOrAllocationSite(r5, r7);
4823 } 5087 }
4824 5088
4825 Label no_info; 5089 Label no_info;
4826 // Get the elements kind and case on that. 5090 // Get the elements kind and case on that.
4827 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); 5091 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
4828 __ b(eq, &no_info); 5092 __ beq(&no_info);
4829 5093
4830 __ ldr(r3, FieldMemOperand(r2, AllocationSite::kTransitionInfoOffset)); 5094 __ LoadP(r6, FieldMemOperand(r5, AllocationSite::kTransitionInfoOffset));
4831 __ SmiUntag(r3); 5095 __ SmiUntag(r6);
4832 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); 5096 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
4833 __ and_(r3, r3, Operand(AllocationSite::ElementsKindBits::kMask)); 5097 __ And(r6, r6, Operand(AllocationSite::ElementsKindBits::kMask));
4834 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); 5098 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE);
4835 5099
4836 __ bind(&no_info); 5100 __ bind(&no_info);
4837 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); 5101 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
4838 } 5102 }
4839 5103
4840 5104
4841 void InternalArrayConstructorStub::GenerateCase( 5105 void InternalArrayConstructorStub::GenerateCase(
4842 MacroAssembler* masm, ElementsKind kind) { 5106 MacroAssembler* masm, ElementsKind kind) {
4843 __ cmp(r0, Operand(1)); 5107 __ cmpli(r3, Operand(1));
4844 5108
4845 InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); 5109 InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
4846 __ TailCallStub(&stub0, lo); 5110 __ TailCallStub(&stub0, lt);
4847 5111
4848 InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); 5112 InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
4849 __ TailCallStub(&stubN, hi); 5113 __ TailCallStub(&stubN, gt);
4850 5114
4851 if (IsFastPackedElementsKind(kind)) { 5115 if (IsFastPackedElementsKind(kind)) {
4852 // We might need to create a holey array 5116 // We might need to create a holey array
4853 // look at the first argument 5117 // look at the first argument
4854 __ ldr(r3, MemOperand(sp, 0)); 5118 __ LoadP(r6, MemOperand(sp, 0));
4855 __ cmp(r3, Operand::Zero()); 5119 __ cmpi(r6, Operand::Zero());
4856 5120
4857 InternalArraySingleArgumentConstructorStub 5121 InternalArraySingleArgumentConstructorStub
4858 stub1_holey(isolate(), GetHoleyElementsKind(kind)); 5122 stub1_holey(isolate(), GetHoleyElementsKind(kind));
4859 __ TailCallStub(&stub1_holey, ne); 5123 __ TailCallStub(&stub1_holey, ne);
4860 } 5124 }
4861 5125
4862 InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); 5126 InternalArraySingleArgumentConstructorStub stub1(isolate(), kind);
4863 __ TailCallStub(&stub1); 5127 __ TailCallStub(&stub1);
4864 } 5128 }
4865 5129
4866 5130
4867 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 5131 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
4868 // ----------- S t a t e ------------- 5132 // ----------- S t a t e -------------
4869 // -- r0 : argc 5133 // -- r3 : argc
4870 // -- r1 : constructor 5134 // -- r4 : constructor
4871 // -- sp[0] : return address 5135 // -- sp[0] : return address
4872 // -- sp[4] : last argument 5136 // -- sp[4] : last argument
4873 // ----------------------------------- 5137 // -----------------------------------
4874 5138
4875 if (FLAG_debug_code) { 5139 if (FLAG_debug_code) {
4876 // The array construct code is only set for the global and natives 5140 // The array construct code is only set for the global and natives
4877 // builtin Array functions which always have maps. 5141 // builtin Array functions which always have maps.
4878 5142
4879 // Initial map for the builtin Array function should be a map. 5143 // Initial map for the builtin Array function should be a map.
4880 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 5144 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
4881 // Will both indicate a NULL and a Smi. 5145 // Will both indicate a NULL and a Smi.
4882 __ tst(r3, Operand(kSmiTagMask)); 5146 __ TestIfSmi(r6, r0);
4883 __ Assert(ne, kUnexpectedInitialMapForArrayFunction); 5147 __ Assert(ne, kUnexpectedInitialMapForArrayFunction, cr0);
4884 __ CompareObjectType(r3, r3, r4, MAP_TYPE); 5148 __ CompareObjectType(r6, r6, r7, MAP_TYPE);
4885 __ Assert(eq, kUnexpectedInitialMapForArrayFunction); 5149 __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
4886 } 5150 }
4887 5151
4888 // Figure out the right elements kind 5152 // Figure out the right elements kind
4889 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 5153 __ LoadP(r6, FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset));
4890 // Load the map's "bit field 2" into |result|. We only need the first byte, 5154 // Load the map's "bit field 2" into |result|.
4891 // but the following bit field extraction takes care of that anyway. 5155 __ lbz(r6, FieldMemOperand(r6, Map::kBitField2Offset));
4892 __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset));
4893 // Retrieve elements_kind from bit field 2. 5156 // Retrieve elements_kind from bit field 2.
4894 __ DecodeField<Map::ElementsKindBits>(r3); 5157 __ DecodeField<Map::ElementsKindBits>(r6);
4895 5158
4896 if (FLAG_debug_code) { 5159 if (FLAG_debug_code) {
4897 Label done; 5160 Label done;
4898 __ cmp(r3, Operand(FAST_ELEMENTS)); 5161 __ cmpi(r6, Operand(FAST_ELEMENTS));
4899 __ b(eq, &done); 5162 __ beq(&done);
4900 __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS)); 5163 __ cmpi(r6, Operand(FAST_HOLEY_ELEMENTS));
4901 __ Assert(eq, 5164 __ Assert(eq,
4902 kInvalidElementsKindForInternalArrayOrInternalPackedArray); 5165 kInvalidElementsKindForInternalArrayOrInternalPackedArray);
4903 __ bind(&done); 5166 __ bind(&done);
4904 } 5167 }
4905 5168
4906 Label fast_elements_case; 5169 Label fast_elements_case;
4907 __ cmp(r3, Operand(FAST_ELEMENTS)); 5170 __ cmpi(r6, Operand(FAST_ELEMENTS));
4908 __ b(eq, &fast_elements_case); 5171 __ beq(&fast_elements_case);
4909 GenerateCase(masm, FAST_HOLEY_ELEMENTS); 5172 GenerateCase(masm, FAST_HOLEY_ELEMENTS);
4910 5173
4911 __ bind(&fast_elements_case); 5174 __ bind(&fast_elements_case);
4912 GenerateCase(masm, FAST_ELEMENTS); 5175 GenerateCase(masm, FAST_ELEMENTS);
4913 } 5176 }
4914 5177
4915 5178
4916 void CallApiFunctionStub::Generate(MacroAssembler* masm) { 5179 void CallApiFunctionStub::Generate(MacroAssembler* masm) {
4917 // ----------- S t a t e ------------- 5180 // ----------- S t a t e -------------
4918 // -- r0 : callee 5181 // -- r3 : callee
4919 // -- r4 : call_data 5182 // -- r7 : call_data
4920 // -- r2 : holder 5183 // -- r5 : holder
4921 // -- r1 : api_function_address 5184 // -- r4 : api_function_address
4922 // -- cp : context 5185 // -- cp : context
4923 // -- 5186 // --
4924 // -- sp[0] : last argument 5187 // -- sp[0] : last argument
4925 // -- ... 5188 // -- ...
4926 // -- sp[(argc - 1)* 4] : first argument 5189 // -- sp[(argc - 1)* 4] : first argument
4927 // -- sp[argc * 4] : receiver 5190 // -- sp[argc * 4] : receiver
4928 // ----------------------------------- 5191 // -----------------------------------
4929 5192
4930 Register callee = r0; 5193 Register callee = r3;
4931 Register call_data = r4; 5194 Register call_data = r7;
4932 Register holder = r2; 5195 Register holder = r5;
4933 Register api_function_address = r1; 5196 Register api_function_address = r4;
4934 Register context = cp; 5197 Register context = cp;
4935 5198
4936 int argc = ArgumentBits::decode(bit_field_); 5199 int argc = ArgumentBits::decode(bit_field_);
4937 bool is_store = IsStoreBits::decode(bit_field_); 5200 bool is_store = IsStoreBits::decode(bit_field_);
4938 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); 5201 bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_);
4939 5202
4940 typedef FunctionCallbackArguments FCA; 5203 typedef FunctionCallbackArguments FCA;
4941 5204
4942 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 5205 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
4943 STATIC_ASSERT(FCA::kCalleeIndex == 5); 5206 STATIC_ASSERT(FCA::kCalleeIndex == 5);
4944 STATIC_ASSERT(FCA::kDataIndex == 4); 5207 STATIC_ASSERT(FCA::kDataIndex == 4);
4945 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 5208 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
4946 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 5209 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
4947 STATIC_ASSERT(FCA::kIsolateIndex == 1); 5210 STATIC_ASSERT(FCA::kIsolateIndex == 1);
4948 STATIC_ASSERT(FCA::kHolderIndex == 0); 5211 STATIC_ASSERT(FCA::kHolderIndex == 0);
4949 STATIC_ASSERT(FCA::kArgsLength == 7); 5212 STATIC_ASSERT(FCA::kArgsLength == 7);
4950 5213
4951 // context save 5214 // context save
4952 __ push(context); 5215 __ push(context);
4953 // load context from callee 5216 // load context from callee
4954 __ ldr(context, FieldMemOperand(callee, JSFunction::kContextOffset)); 5217 __ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset));
4955 5218
4956 // callee 5219 // callee
4957 __ push(callee); 5220 __ push(callee);
4958 5221
4959 // call data 5222 // call data
4960 __ push(call_data); 5223 __ push(call_data);
4961 5224
4962 Register scratch = call_data; 5225 Register scratch = call_data;
4963 if (!call_data_undefined) { 5226 if (!call_data_undefined) {
4964 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 5227 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
4965 } 5228 }
4966 // return value 5229 // return value
4967 __ push(scratch); 5230 __ push(scratch);
4968 // return value default 5231 // return value default
4969 __ push(scratch); 5232 __ push(scratch);
4970 // isolate 5233 // isolate
4971 __ mov(scratch, 5234 __ mov(scratch,
4972 Operand(ExternalReference::isolate_address(isolate()))); 5235 Operand(ExternalReference::isolate_address(isolate())));
4973 __ push(scratch); 5236 __ push(scratch);
4974 // holder 5237 // holder
4975 __ push(holder); 5238 __ push(holder);
4976 5239
4977 // Prepare arguments. 5240 // Prepare arguments.
4978 __ mov(scratch, sp); 5241 __ mr(scratch, sp);
4979 5242
4980 // Allocate the v8::Arguments structure in the arguments' space since 5243 // Allocate the v8::Arguments structure in the arguments' space since
4981 // it's not controlled by GC. 5244 // it's not controlled by GC.
4982 const int kApiStackSpace = 4; 5245 // PPC LINUX ABI:
5246 //
5247 // Create 5 extra slots on stack:
5248 // [0] space for DirectCEntryStub's LR save
5249 // [1-4] FunctionCallbackInfo
5250 const int kApiStackSpace = 5;
4983 5251
4984 FrameScope frame_scope(masm, StackFrame::MANUAL); 5252 FrameScope frame_scope(masm, StackFrame::MANUAL);
4985 __ EnterExitFrame(false, kApiStackSpace); 5253 __ EnterExitFrame(false, kApiStackSpace);
4986 5254
4987 ASSERT(!api_function_address.is(r0) && !scratch.is(r0)); 5255 ASSERT(!api_function_address.is(r3) && !scratch.is(r3));
4988 // r0 = FunctionCallbackInfo& 5256 // r3 = FunctionCallbackInfo&
4989 // Arguments is after the return address. 5257 // Arguments is after the return address.
4990 __ add(r0, sp, Operand(1 * kPointerSize)); 5258 __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
4991 // FunctionCallbackInfo::implicit_args_ 5259 // FunctionCallbackInfo::implicit_args_
4992 __ str(scratch, MemOperand(r0, 0 * kPointerSize)); 5260 __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize));
4993 // FunctionCallbackInfo::values_ 5261 // FunctionCallbackInfo::values_
4994 __ add(ip, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize)); 5262 __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize));
4995 __ str(ip, MemOperand(r0, 1 * kPointerSize)); 5263 __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
4996 // FunctionCallbackInfo::length_ = argc 5264 // FunctionCallbackInfo::length_ = argc
4997 __ mov(ip, Operand(argc)); 5265 __ li(ip, Operand(argc));
4998 __ str(ip, MemOperand(r0, 2 * kPointerSize)); 5266 __ stw(ip, MemOperand(r3, 2 * kPointerSize));
4999 // FunctionCallbackInfo::is_construct_call = 0 5267 // FunctionCallbackInfo::is_construct_call = 0
5000 __ mov(ip, Operand::Zero()); 5268 __ li(ip, Operand::Zero());
5001 __ str(ip, MemOperand(r0, 3 * kPointerSize)); 5269 __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
5002 5270
5003 const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; 5271 const int kStackUnwindSpace = argc + FCA::kArgsLength + 1;
5004 ExternalReference thunk_ref = 5272 ExternalReference thunk_ref =
5005 ExternalReference::invoke_function_callback(isolate()); 5273 ExternalReference::invoke_function_callback(isolate());
5006 5274
5007 AllowExternalCallThatCantCauseGC scope(masm); 5275 AllowExternalCallThatCantCauseGC scope(masm);
5008 MemOperand context_restore_operand( 5276 MemOperand context_restore_operand(
5009 fp, (2 + FCA::kContextSaveIndex) * kPointerSize); 5277 fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
5010 // Stores return the first js argument 5278 // Stores return the first js argument
5011 int return_value_offset = 0; 5279 int return_value_offset = 0;
(...skipping 10 matching lines...) Expand all
5022 return_value_operand, 5290 return_value_operand,
5023 &context_restore_operand); 5291 &context_restore_operand);
5024 } 5292 }
5025 5293
5026 5294
5027 void CallApiGetterStub::Generate(MacroAssembler* masm) { 5295 void CallApiGetterStub::Generate(MacroAssembler* masm) {
5028 // ----------- S t a t e ------------- 5296 // ----------- S t a t e -------------
5029 // -- sp[0] : name 5297 // -- sp[0] : name
5030 // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object 5298 // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object
5031 // -- ... 5299 // -- ...
5032 // -- r2 : api_function_address 5300 // -- r5 : api_function_address
5033 // ----------------------------------- 5301 // -----------------------------------
5034 5302
5035 Register api_function_address = r2; 5303 Register api_function_address = r5;
5036 5304
5037 __ mov(r0, sp); // r0 = Handle<Name> 5305 __ mr(r3, sp); // r0 = Handle<Name>
5038 __ add(r1, r0, Operand(1 * kPointerSize)); // r1 = PCA 5306 __ addi(r4, r3, Operand(1 * kPointerSize)); // r4 = PCA
5039 5307
5040 const int kApiStackSpace = 1; 5308 // If ABI passes Handles (pointer-sized struct) in a register:
5309 //
5310 // Create 2 extra slots on stack:
5311 // [0] space for DirectCEntryStub's LR save
5312 // [1] AccessorInfo&
5313 //
5314 // Otherwise:
5315 //
5316 // Create 3 extra slots on stack:
5317 // [0] space for DirectCEntryStub's LR save
5318 // [1] copy of Handle (first arg)
5319 // [2] AccessorInfo&
5320 #if ABI_PASSES_HANDLES_IN_REGS
5321 const int kAccessorInfoSlot = kStackFrameExtraParamSlot + 1;
5322 const int kApiStackSpace = 2;
5323 #else
5324 const int kArg0Slot = kStackFrameExtraParamSlot + 1;
5325 const int kAccessorInfoSlot = kArg0Slot + 1;
5326 const int kApiStackSpace = 3;
5327 #endif
5328
5041 FrameScope frame_scope(masm, StackFrame::MANUAL); 5329 FrameScope frame_scope(masm, StackFrame::MANUAL);
5042 __ EnterExitFrame(false, kApiStackSpace); 5330 __ EnterExitFrame(false, kApiStackSpace);
5043 5331
5332 #if !ABI_PASSES_HANDLES_IN_REGS
5333 // pass 1st arg by reference
5334 __ StoreP(r3,
5335 MemOperand(sp, kArg0Slot * kPointerSize));
5336 __ addi(r3, sp, Operand(kArg0Slot * kPointerSize));
5337 #endif
5338
5044 // Create PropertyAccessorInfo instance on the stack above the exit frame with 5339 // Create PropertyAccessorInfo instance on the stack above the exit frame with
5045 // r1 (internal::Object** args_) as the data. 5340 // r4 (internal::Object** args_) as the data.
5046 __ str(r1, MemOperand(sp, 1 * kPointerSize)); 5341 __ StoreP(r4, MemOperand(sp, kAccessorInfoSlot * kPointerSize));
5047 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& 5342 // r4 = AccessorInfo&
5343 __ addi(r4, sp, Operand(kAccessorInfoSlot * kPointerSize));
5048 5344
5049 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; 5345 const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
5050 5346
5051 ExternalReference thunk_ref = 5347 ExternalReference thunk_ref =
5052 ExternalReference::invoke_accessor_getter_callback(isolate()); 5348 ExternalReference::invoke_accessor_getter_callback(isolate());
5053 __ CallApiFunctionAndReturn(api_function_address, 5349 __ CallApiFunctionAndReturn(api_function_address,
5054 thunk_ref, 5350 thunk_ref,
5055 kStackUnwindSpace, 5351 kStackUnwindSpace,
5056 MemOperand(fp, 6 * kPointerSize), 5352 MemOperand(fp, 6 * kPointerSize),
5057 NULL); 5353 NULL);
5058 } 5354 }
5059 5355
5060 5356
5061 #undef __ 5357 #undef __
5062 5358
5063 } } // namespace v8::internal 5359 } } // namespace v8::internal
5064 5360
5065 #endif // V8_TARGET_ARCH_ARM 5361 #endif // V8_TARGET_ARCH_PPC
OLDNEW
« src/objects-inl.h ('K') | « src/ppc/code-stubs-ppc.h ('k') | src/ppc/codegen-ppc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698