OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
11 #include "src/stub-cache.h" | 11 #include "src/stub-cache.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 | 16 |
17 #define __ ACCESS_MASM(masm) | 17 #define __ ACCESS_MASM(masm) |
18 | 18 |
19 | 19 |
20 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 20 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
21 MacroAssembler* masm, Label* miss_label, Register receiver, | 21 MacroAssembler* masm, Label* miss_label, Register receiver, |
22 Handle<Name> name, Register scratch0, Register scratch1) { | 22 Handle<Name> name, Register scratch0, Register scratch1) { |
23 ASSERT(!AreAliased(receiver, scratch0, scratch1)); | 23 DCHECK(!AreAliased(receiver, scratch0, scratch1)); |
24 ASSERT(name->IsUniqueName()); | 24 DCHECK(name->IsUniqueName()); |
25 Counters* counters = masm->isolate()->counters(); | 25 Counters* counters = masm->isolate()->counters(); |
26 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 26 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
27 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 27 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
28 | 28 |
29 Label done; | 29 Label done; |
30 | 30 |
31 const int kInterceptorOrAccessCheckNeededMask = | 31 const int kInterceptorOrAccessCheckNeededMask = |
32 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 32 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
33 | 33 |
34 // Bail out if the receiver has a named interceptor or requires access checks. | 34 // Bail out if the receiver has a named interceptor or requires access checks. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); | 86 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
87 ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); | 87 ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); |
88 | 88 |
89 uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address()); | 89 uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address()); |
90 uintptr_t value_off_addr = | 90 uintptr_t value_off_addr = |
91 reinterpret_cast<uintptr_t>(value_offset.address()); | 91 reinterpret_cast<uintptr_t>(value_offset.address()); |
92 uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address()); | 92 uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address()); |
93 | 93 |
94 Label miss; | 94 Label miss; |
95 | 95 |
96 ASSERT(!AreAliased(name, offset, scratch, scratch2, scratch3)); | 96 DCHECK(!AreAliased(name, offset, scratch, scratch2, scratch3)); |
97 | 97 |
98 // Multiply by 3 because there are 3 fields per entry. | 98 // Multiply by 3 because there are 3 fields per entry. |
99 __ Add(scratch3, offset, Operand(offset, LSL, 1)); | 99 __ Add(scratch3, offset, Operand(offset, LSL, 1)); |
100 | 100 |
101 // Calculate the base address of the entry. | 101 // Calculate the base address of the entry. |
102 __ Mov(scratch, key_offset); | 102 __ Mov(scratch, key_offset); |
103 __ Add(scratch, scratch, Operand(scratch3, LSL, kPointerSizeLog2)); | 103 __ Add(scratch, scratch, Operand(scratch3, LSL, kPointerSizeLog2)); |
104 | 104 |
105 // Check that the key in the entry matches the name. | 105 // Check that the key in the entry matches the name. |
106 __ Ldr(scratch2, MemOperand(scratch)); | 106 __ Ldr(scratch2, MemOperand(scratch)); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 Register receiver, | 144 Register receiver, |
145 Register name, | 145 Register name, |
146 Register scratch, | 146 Register scratch, |
147 Register extra, | 147 Register extra, |
148 Register extra2, | 148 Register extra2, |
149 Register extra3) { | 149 Register extra3) { |
150 Isolate* isolate = masm->isolate(); | 150 Isolate* isolate = masm->isolate(); |
151 Label miss; | 151 Label miss; |
152 | 152 |
153 // Make sure the flags does not name a specific type. | 153 // Make sure the flags does not name a specific type. |
154 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 154 DCHECK(Code::ExtractTypeFromFlags(flags) == 0); |
155 | 155 |
156 // Make sure that there are no register conflicts. | 156 // Make sure that there are no register conflicts. |
157 ASSERT(!AreAliased(receiver, name, scratch, extra, extra2, extra3)); | 157 DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3)); |
158 | 158 |
159 // Make sure extra and extra2 registers are valid. | 159 // Make sure extra and extra2 registers are valid. |
160 ASSERT(!extra.is(no_reg)); | 160 DCHECK(!extra.is(no_reg)); |
161 ASSERT(!extra2.is(no_reg)); | 161 DCHECK(!extra2.is(no_reg)); |
162 ASSERT(!extra3.is(no_reg)); | 162 DCHECK(!extra3.is(no_reg)); |
163 | 163 |
164 Counters* counters = masm->isolate()->counters(); | 164 Counters* counters = masm->isolate()->counters(); |
165 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, | 165 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, |
166 extra2, extra3); | 166 extra2, extra3); |
167 | 167 |
168 // Check that the receiver isn't a smi. | 168 // Check that the receiver isn't a smi. |
169 __ JumpIfSmi(receiver, &miss); | 169 __ JumpIfSmi(receiver, &miss); |
170 | 170 |
171 // Compute the hash for primary table. | 171 // Compute the hash for primary table. |
172 __ Ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); | 172 __ Ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 } | 233 } |
234 | 234 |
235 | 235 |
236 // Generate code to check that a global property cell is empty. Create | 236 // Generate code to check that a global property cell is empty. Create |
237 // the property cell at compilation time if no cell exists for the | 237 // the property cell at compilation time if no cell exists for the |
238 // property. | 238 // property. |
239 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 239 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
240 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 240 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
241 Register scratch, Label* miss) { | 241 Register scratch, Label* miss) { |
242 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 242 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
243 ASSERT(cell->value()->IsTheHole()); | 243 DCHECK(cell->value()->IsTheHole()); |
244 __ Mov(scratch, Operand(cell)); | 244 __ Mov(scratch, Operand(cell)); |
245 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 245 __ Ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
246 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); | 246 __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss); |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, | 250 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, |
251 Register holder, Register name, | 251 Register holder, Register name, |
252 Handle<JSObject> holder_obj) { | 252 Handle<JSObject> holder_obj) { |
253 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 253 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
254 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 254 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); |
255 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 255 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); |
256 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 256 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); |
257 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | 257 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); |
258 | 258 |
259 __ Push(name); | 259 __ Push(name); |
260 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 260 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
261 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 261 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
262 Register scratch = name; | 262 Register scratch = name; |
263 __ Mov(scratch, Operand(interceptor)); | 263 __ Mov(scratch, Operand(interceptor)); |
264 __ Push(scratch, receiver, holder); | 264 __ Push(scratch, receiver, holder); |
265 } | 265 } |
266 | 266 |
267 | 267 |
268 static void CompileCallLoadPropertyWithInterceptor( | 268 static void CompileCallLoadPropertyWithInterceptor( |
269 MacroAssembler* masm, Register receiver, Register holder, Register name, | 269 MacroAssembler* masm, Register receiver, Register holder, Register name, |
270 Handle<JSObject> holder_obj, IC::UtilityId id) { | 270 Handle<JSObject> holder_obj, IC::UtilityId id) { |
271 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 271 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
272 | 272 |
273 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | 273 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |
274 NamedLoadHandlerCompiler::kInterceptorArgsLength); | 274 NamedLoadHandlerCompiler::kInterceptorArgsLength); |
275 } | 275 } |
276 | 276 |
277 | 277 |
278 // Generate call to api function. | 278 // Generate call to api function. |
279 void PropertyHandlerCompiler::GenerateFastApiCall( | 279 void PropertyHandlerCompiler::GenerateFastApiCall( |
280 MacroAssembler* masm, const CallOptimization& optimization, | 280 MacroAssembler* masm, const CallOptimization& optimization, |
281 Handle<Map> receiver_map, Register receiver, Register scratch, | 281 Handle<Map> receiver_map, Register receiver, Register scratch, |
282 bool is_store, int argc, Register* values) { | 282 bool is_store, int argc, Register* values) { |
283 ASSERT(!AreAliased(receiver, scratch)); | 283 DCHECK(!AreAliased(receiver, scratch)); |
284 | 284 |
285 MacroAssembler::PushPopQueue queue(masm); | 285 MacroAssembler::PushPopQueue queue(masm); |
286 queue.Queue(receiver); | 286 queue.Queue(receiver); |
287 // Write the arguments to the stack frame. | 287 // Write the arguments to the stack frame. |
288 for (int i = 0; i < argc; i++) { | 288 for (int i = 0; i < argc; i++) { |
289 Register arg = values[argc - 1 - i]; | 289 Register arg = values[argc - 1 - i]; |
290 ASSERT(!AreAliased(receiver, scratch, arg)); | 290 DCHECK(!AreAliased(receiver, scratch, arg)); |
291 queue.Queue(arg); | 291 queue.Queue(arg); |
292 } | 292 } |
293 queue.PushQueued(); | 293 queue.PushQueued(); |
294 | 294 |
295 ASSERT(optimization.is_simple_api_call()); | 295 DCHECK(optimization.is_simple_api_call()); |
296 | 296 |
297 // Abi for CallApiFunctionStub. | 297 // Abi for CallApiFunctionStub. |
298 Register callee = x0; | 298 Register callee = x0; |
299 Register call_data = x4; | 299 Register call_data = x4; |
300 Register holder = x2; | 300 Register holder = x2; |
301 Register api_function_address = x1; | 301 Register api_function_address = x1; |
302 | 302 |
303 // Put holder in place. | 303 // Put holder in place. |
304 CallOptimization::HolderLookup holder_lookup; | 304 CallOptimization::HolderLookup holder_lookup; |
305 Handle<JSObject> api_holder = | 305 Handle<JSObject> api_holder = |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 // Generate StoreTransition code, value is passed in x0 register. | 371 // Generate StoreTransition code, value is passed in x0 register. |
372 // When leaving generated code after success, the receiver_reg and storage_reg | 372 // When leaving generated code after success, the receiver_reg and storage_reg |
373 // may be clobbered. Upon branch to miss_label, the receiver and name registers | 373 // may be clobbered. Upon branch to miss_label, the receiver and name registers |
374 // have their original values. | 374 // have their original values. |
375 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 375 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
376 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 376 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
377 Register storage_reg, Register value_reg, Register scratch1, | 377 Register storage_reg, Register value_reg, Register scratch1, |
378 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { | 378 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { |
379 Label exit; | 379 Label exit; |
380 | 380 |
381 ASSERT(!AreAliased(receiver_reg, storage_reg, value_reg, | 381 DCHECK(!AreAliased(receiver_reg, storage_reg, value_reg, |
382 scratch1, scratch2, scratch3)); | 382 scratch1, scratch2, scratch3)); |
383 | 383 |
384 // We don't need scratch3. | 384 // We don't need scratch3. |
385 scratch3 = NoReg; | 385 scratch3 = NoReg; |
386 | 386 |
387 int descriptor = transition->LastAdded(); | 387 int descriptor = transition->LastAdded(); |
388 DescriptorArray* descriptors = transition->instance_descriptors(); | 388 DescriptorArray* descriptors = transition->instance_descriptors(); |
389 PropertyDetails details = descriptors->GetDetails(descriptor); | 389 PropertyDetails details = descriptors->GetDetails(descriptor); |
390 Representation representation = details.representation(); | 390 Representation representation = details.representation(); |
391 ASSERT(!representation.IsNone()); | 391 DCHECK(!representation.IsNone()); |
392 | 392 |
393 if (details.type() == CONSTANT) { | 393 if (details.type() == CONSTANT) { |
394 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); | 394 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); |
395 __ LoadObject(scratch1, constant); | 395 __ LoadObject(scratch1, constant); |
396 __ Cmp(value_reg, scratch1); | 396 __ Cmp(value_reg, scratch1); |
397 __ B(ne, miss_label); | 397 __ B(ne, miss_label); |
398 } else if (representation.IsSmi()) { | 398 } else if (representation.IsSmi()) { |
399 __ JumpIfNotSmi(value_reg, miss_label); | 399 __ JumpIfNotSmi(value_reg, miss_label); |
400 } else if (representation.IsHeapObject()) { | 400 } else if (representation.IsHeapObject()) { |
401 __ JumpIfSmi(value_reg, miss_label); | 401 __ JumpIfSmi(value_reg, miss_label); |
(...skipping 24 matching lines...) Expand all Loading... |
426 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 426 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
427 miss_label, DONT_DO_SMI_CHECK); | 427 miss_label, DONT_DO_SMI_CHECK); |
428 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 428 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
429 | 429 |
430 __ Bind(&do_store); | 430 __ Bind(&do_store); |
431 __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2, temp_double, | 431 __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2, temp_double, |
432 NoReg, MUTABLE); | 432 NoReg, MUTABLE); |
433 } | 433 } |
434 | 434 |
435 // Stub never generated for objects that require access checks. | 435 // Stub never generated for objects that require access checks. |
436 ASSERT(!transition->is_access_check_needed()); | 436 DCHECK(!transition->is_access_check_needed()); |
437 | 437 |
438 // Perform map transition for the receiver if necessary. | 438 // Perform map transition for the receiver if necessary. |
439 if (details.type() == FIELD && | 439 if (details.type() == FIELD && |
440 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 440 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
441 // The properties must be extended before we can store the value. | 441 // The properties must be extended before we can store the value. |
442 // We jump to a runtime call that extends the properties array. | 442 // We jump to a runtime call that extends the properties array. |
443 __ Mov(scratch1, Operand(transition)); | 443 __ Mov(scratch1, Operand(transition)); |
444 __ Push(receiver_reg, scratch1, value_reg); | 444 __ Push(receiver_reg, scratch1, value_reg); |
445 __ TailCallExternalReference( | 445 __ TailCallExternalReference( |
446 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 446 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
(...skipping 10 matching lines...) Expand all Loading... |
457 __ RecordWriteField(receiver_reg, | 457 __ RecordWriteField(receiver_reg, |
458 HeapObject::kMapOffset, | 458 HeapObject::kMapOffset, |
459 scratch1, | 459 scratch1, |
460 scratch2, | 460 scratch2, |
461 kLRHasNotBeenSaved, | 461 kLRHasNotBeenSaved, |
462 kDontSaveFPRegs, | 462 kDontSaveFPRegs, |
463 OMIT_REMEMBERED_SET, | 463 OMIT_REMEMBERED_SET, |
464 OMIT_SMI_CHECK); | 464 OMIT_SMI_CHECK); |
465 | 465 |
466 if (details.type() == CONSTANT) { | 466 if (details.type() == CONSTANT) { |
467 ASSERT(value_reg.is(x0)); | 467 DCHECK(value_reg.is(x0)); |
468 __ Ret(); | 468 __ Ret(); |
469 return; | 469 return; |
470 } | 470 } |
471 | 471 |
472 int index = transition->instance_descriptors()->GetFieldIndex( | 472 int index = transition->instance_descriptors()->GetFieldIndex( |
473 transition->LastAdded()); | 473 transition->LastAdded()); |
474 | 474 |
475 // Adjust for the number of properties stored in the object. Even in the | 475 // Adjust for the number of properties stored in the object. Even in the |
476 // face of a transition we can use the old map here because the size of the | 476 // face of a transition we can use the old map here because the size of the |
477 // object and the number of in-object properties is not going to change. | 477 // object and the number of in-object properties is not going to change. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 receiver_reg, | 519 receiver_reg, |
520 kLRHasNotBeenSaved, | 520 kLRHasNotBeenSaved, |
521 kDontSaveFPRegs, | 521 kDontSaveFPRegs, |
522 EMIT_REMEMBERED_SET, | 522 EMIT_REMEMBERED_SET, |
523 smi_check); | 523 smi_check); |
524 } | 524 } |
525 } | 525 } |
526 | 526 |
527 __ Bind(&exit); | 527 __ Bind(&exit); |
528 // Return the value (register x0). | 528 // Return the value (register x0). |
529 ASSERT(value_reg.is(x0)); | 529 DCHECK(value_reg.is(x0)); |
530 __ Ret(); | 530 __ Ret(); |
531 } | 531 } |
532 | 532 |
533 | 533 |
534 // Generate StoreField code, value is passed in x0 register. | 534 // Generate StoreField code, value is passed in x0 register. |
535 // When leaving generated code after success, the receiver_reg and name_reg may | 535 // When leaving generated code after success, the receiver_reg and name_reg may |
536 // be clobbered. Upon branch to miss_label, the receiver and name registers have | 536 // be clobbered. Upon branch to miss_label, the receiver and name registers have |
537 // their original values. | 537 // their original values. |
538 void NamedStoreHandlerCompiler::GenerateStoreField( | 538 void NamedStoreHandlerCompiler::GenerateStoreField( |
539 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, | 539 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, |
540 Register name_reg, Register value_reg, Register scratch1, Register scratch2, | 540 Register name_reg, Register value_reg, Register scratch1, Register scratch2, |
541 Label* miss_label) { | 541 Label* miss_label) { |
542 // x0 : value | 542 // x0 : value |
543 Label exit; | 543 Label exit; |
544 | 544 |
545 // Stub never generated for objects that require access checks. | 545 // Stub never generated for objects that require access checks. |
546 ASSERT(!object->IsAccessCheckNeeded()); | 546 DCHECK(!object->IsAccessCheckNeeded()); |
547 ASSERT(!object->IsJSGlobalProxy()); | 547 DCHECK(!object->IsJSGlobalProxy()); |
548 | 548 |
549 FieldIndex index = lookup->GetFieldIndex(); | 549 FieldIndex index = lookup->GetFieldIndex(); |
550 | 550 |
551 Representation representation = lookup->representation(); | 551 Representation representation = lookup->representation(); |
552 ASSERT(!representation.IsNone()); | 552 DCHECK(!representation.IsNone()); |
553 if (representation.IsSmi()) { | 553 if (representation.IsSmi()) { |
554 __ JumpIfNotSmi(value_reg, miss_label); | 554 __ JumpIfNotSmi(value_reg, miss_label); |
555 } else if (representation.IsHeapObject()) { | 555 } else if (representation.IsHeapObject()) { |
556 __ JumpIfSmi(value_reg, miss_label); | 556 __ JumpIfSmi(value_reg, miss_label); |
557 HeapType* field_type = lookup->GetFieldType(); | 557 HeapType* field_type = lookup->GetFieldType(); |
558 HeapType::Iterator<Map> it = field_type->Classes(); | 558 HeapType::Iterator<Map> it = field_type->Classes(); |
559 if (!it.Done()) { | 559 if (!it.Done()) { |
560 __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 560 __ Ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
561 Label do_store; | 561 Label do_store; |
562 while (true) { | 562 while (true) { |
(...skipping 28 matching lines...) Expand all Loading... |
591 __ JumpIfSmi(value_reg, &do_store); | 591 __ JumpIfSmi(value_reg, &do_store); |
592 | 592 |
593 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, | 593 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, |
594 miss_label, DONT_DO_SMI_CHECK); | 594 miss_label, DONT_DO_SMI_CHECK); |
595 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 595 __ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
596 | 596 |
597 __ Bind(&do_store); | 597 __ Bind(&do_store); |
598 __ Str(temp_double, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); | 598 __ Str(temp_double, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); |
599 | 599 |
600 // Return the value (register x0). | 600 // Return the value (register x0). |
601 ASSERT(value_reg.is(x0)); | 601 DCHECK(value_reg.is(x0)); |
602 __ Ret(); | 602 __ Ret(); |
603 return; | 603 return; |
604 } | 604 } |
605 | 605 |
606 // TODO(verwaest): Share this code as a code stub. | 606 // TODO(verwaest): Share this code as a code stub. |
607 SmiCheck smi_check = representation.IsTagged() | 607 SmiCheck smi_check = representation.IsTagged() |
608 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 608 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
609 if (index.is_inobject()) { | 609 if (index.is_inobject()) { |
610 // Set the property straight into the object. | 610 // Set the property straight into the object. |
611 __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset())); | 611 __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset())); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 receiver_reg, | 646 receiver_reg, |
647 kLRHasNotBeenSaved, | 647 kLRHasNotBeenSaved, |
648 kDontSaveFPRegs, | 648 kDontSaveFPRegs, |
649 EMIT_REMEMBERED_SET, | 649 EMIT_REMEMBERED_SET, |
650 smi_check); | 650 smi_check); |
651 } | 651 } |
652 } | 652 } |
653 | 653 |
654 __ Bind(&exit); | 654 __ Bind(&exit); |
655 // Return the value (register x0). | 655 // Return the value (register x0). |
656 ASSERT(value_reg.is(x0)); | 656 DCHECK(value_reg.is(x0)); |
657 __ Ret(); | 657 __ Ret(); |
658 } | 658 } |
659 | 659 |
660 | 660 |
661 Register PropertyHandlerCompiler::CheckPrototypes( | 661 Register PropertyHandlerCompiler::CheckPrototypes( |
662 Register object_reg, Register holder_reg, Register scratch1, | 662 Register object_reg, Register holder_reg, Register scratch1, |
663 Register scratch2, Handle<Name> name, Label* miss, | 663 Register scratch2, Handle<Name> name, Label* miss, |
664 PrototypeCheckType check) { | 664 PrototypeCheckType check) { |
665 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 665 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
666 | 666 |
667 // object_reg and holder_reg registers can alias. | 667 // object_reg and holder_reg registers can alias. |
668 ASSERT(!AreAliased(object_reg, scratch1, scratch2)); | 668 DCHECK(!AreAliased(object_reg, scratch1, scratch2)); |
669 ASSERT(!AreAliased(holder_reg, scratch1, scratch2)); | 669 DCHECK(!AreAliased(holder_reg, scratch1, scratch2)); |
670 | 670 |
671 // Keep track of the current object in register reg. | 671 // Keep track of the current object in register reg. |
672 Register reg = object_reg; | 672 Register reg = object_reg; |
673 int depth = 0; | 673 int depth = 0; |
674 | 674 |
675 Handle<JSObject> current = Handle<JSObject>::null(); | 675 Handle<JSObject> current = Handle<JSObject>::null(); |
676 if (type()->IsConstant()) { | 676 if (type()->IsConstant()) { |
677 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 677 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
678 } | 678 } |
679 Handle<JSObject> prototype = Handle<JSObject>::null(); | 679 Handle<JSObject> prototype = Handle<JSObject>::null(); |
680 Handle<Map> current_map = receiver_map; | 680 Handle<Map> current_map = receiver_map; |
681 Handle<Map> holder_map(holder()->map()); | 681 Handle<Map> holder_map(holder()->map()); |
682 // Traverse the prototype chain and check the maps in the prototype chain for | 682 // Traverse the prototype chain and check the maps in the prototype chain for |
683 // fast and global objects or do negative lookup for normal objects. | 683 // fast and global objects or do negative lookup for normal objects. |
684 while (!current_map.is_identical_to(holder_map)) { | 684 while (!current_map.is_identical_to(holder_map)) { |
685 ++depth; | 685 ++depth; |
686 | 686 |
687 // Only global objects and objects that do not require access | 687 // Only global objects and objects that do not require access |
688 // checks are allowed in stubs. | 688 // checks are allowed in stubs. |
689 ASSERT(current_map->IsJSGlobalProxyMap() || | 689 DCHECK(current_map->IsJSGlobalProxyMap() || |
690 !current_map->is_access_check_needed()); | 690 !current_map->is_access_check_needed()); |
691 | 691 |
692 prototype = handle(JSObject::cast(current_map->prototype())); | 692 prototype = handle(JSObject::cast(current_map->prototype())); |
693 if (current_map->is_dictionary_map() && | 693 if (current_map->is_dictionary_map() && |
694 !current_map->IsJSGlobalObjectMap() && | 694 !current_map->IsJSGlobalObjectMap() && |
695 !current_map->IsJSGlobalProxyMap()) { | 695 !current_map->IsJSGlobalProxyMap()) { |
696 if (!name->IsUniqueName()) { | 696 if (!name->IsUniqueName()) { |
697 ASSERT(name->IsString()); | 697 DCHECK(name->IsString()); |
698 name = factory()->InternalizeString(Handle<String>::cast(name)); | 698 name = factory()->InternalizeString(Handle<String>::cast(name)); |
699 } | 699 } |
700 ASSERT(current.is_null() || | 700 DCHECK(current.is_null() || |
701 (current->property_dictionary()->FindEntry(name) == | 701 (current->property_dictionary()->FindEntry(name) == |
702 NameDictionary::kNotFound)); | 702 NameDictionary::kNotFound)); |
703 | 703 |
704 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 704 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
705 scratch1, scratch2); | 705 scratch1, scratch2); |
706 | 706 |
707 __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 707 __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
708 reg = holder_reg; // From now on the object will be in holder_reg. | 708 reg = holder_reg; // From now on the object will be in holder_reg. |
709 __ Ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 709 __ Ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
710 } else { | 710 } else { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 // Log the check depth. | 750 // Log the check depth. |
751 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 751 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
752 | 752 |
753 // Check the holder map. | 753 // Check the holder map. |
754 if (depth != 0 || check == CHECK_ALL_MAPS) { | 754 if (depth != 0 || check == CHECK_ALL_MAPS) { |
755 // Check the holder map. | 755 // Check the holder map. |
756 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); | 756 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); |
757 } | 757 } |
758 | 758 |
759 // Perform security check for access to the global object. | 759 // Perform security check for access to the global object. |
760 ASSERT(current_map->IsJSGlobalProxyMap() || | 760 DCHECK(current_map->IsJSGlobalProxyMap() || |
761 !current_map->is_access_check_needed()); | 761 !current_map->is_access_check_needed()); |
762 if (current_map->IsJSGlobalProxyMap()) { | 762 if (current_map->IsJSGlobalProxyMap()) { |
763 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 763 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
764 } | 764 } |
765 | 765 |
766 // Return the register containing the holder. | 766 // Return the register containing the holder. |
767 return reg; | 767 return reg; |
768 } | 768 } |
769 | 769 |
770 | 770 |
(...skipping 27 matching lines...) Expand all Loading... |
798 Handle<Name> name, | 798 Handle<Name> name, |
799 Handle<Object> callback) { | 799 Handle<Object> callback) { |
800 Label miss; | 800 Label miss; |
801 | 801 |
802 Register reg = FrontendHeader(object_reg, name, &miss); | 802 Register reg = FrontendHeader(object_reg, name, &miss); |
803 // FrontendHeader can return its result into scratch1() so do not | 803 // FrontendHeader can return its result into scratch1() so do not |
804 // use it. | 804 // use it. |
805 Register scratch2 = this->scratch2(); | 805 Register scratch2 = this->scratch2(); |
806 Register scratch3 = this->scratch3(); | 806 Register scratch3 = this->scratch3(); |
807 Register dictionary = this->scratch4(); | 807 Register dictionary = this->scratch4(); |
808 ASSERT(!AreAliased(reg, scratch2, scratch3, dictionary)); | 808 DCHECK(!AreAliased(reg, scratch2, scratch3, dictionary)); |
809 | 809 |
810 if (!holder()->HasFastProperties()) { | 810 if (!holder()->HasFastProperties()) { |
811 ASSERT(!holder()->IsGlobalObject()); | 811 DCHECK(!holder()->IsGlobalObject()); |
812 // Load the properties dictionary. | 812 // Load the properties dictionary. |
813 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 813 __ Ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
814 | 814 |
815 // Probe the dictionary. | 815 // Probe the dictionary. |
816 Label probe_done; | 816 Label probe_done; |
817 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), | 817 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), |
818 &miss, | 818 &miss, |
819 &probe_done, | 819 &probe_done, |
820 dictionary, | 820 dictionary, |
821 this->name(), | 821 this->name(), |
(...skipping 27 matching lines...) Expand all Loading... |
849 | 849 |
850 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 850 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
851 // Return the constant value. | 851 // Return the constant value. |
852 __ LoadObject(x0, value); | 852 __ LoadObject(x0, value); |
853 __ Ret(); | 853 __ Ret(); |
854 } | 854 } |
855 | 855 |
856 | 856 |
857 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 857 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
858 Register reg, Handle<ExecutableAccessorInfo> callback) { | 858 Register reg, Handle<ExecutableAccessorInfo> callback) { |
859 ASSERT(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); | 859 DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); |
860 | 860 |
861 // Build ExecutableAccessorInfo::args_ list on the stack and push property | 861 // Build ExecutableAccessorInfo::args_ list on the stack and push property |
862 // name below the exit frame to make GC aware of them and store pointers to | 862 // name below the exit frame to make GC aware of them and store pointers to |
863 // them. | 863 // them. |
864 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 864 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
865 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 865 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
866 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 866 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
867 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 867 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
868 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 868 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
869 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 869 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 __ Mov(getter_address_reg, ref); | 904 __ Mov(getter_address_reg, ref); |
905 | 905 |
906 CallApiGetterStub stub(isolate()); | 906 CallApiGetterStub stub(isolate()); |
907 __ TailCallStub(&stub); | 907 __ TailCallStub(&stub); |
908 } | 908 } |
909 | 909 |
910 | 910 |
911 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, | 911 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
912 LookupResult* lookup, | 912 LookupResult* lookup, |
913 Handle<Name> name) { | 913 Handle<Name> name) { |
914 ASSERT(!AreAliased(receiver(), this->name(), | 914 DCHECK(!AreAliased(receiver(), this->name(), |
915 scratch1(), scratch2(), scratch3())); | 915 scratch1(), scratch2(), scratch3())); |
916 ASSERT(holder()->HasNamedInterceptor()); | 916 DCHECK(holder()->HasNamedInterceptor()); |
917 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 917 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
918 | 918 |
919 // So far the most popular follow ups for interceptor loads are FIELD | 919 // So far the most popular follow ups for interceptor loads are FIELD |
920 // and CALLBACKS, so inline only them, other cases may be added later. | 920 // and CALLBACKS, so inline only them, other cases may be added later. |
921 bool compile_followup_inline = false; | 921 bool compile_followup_inline = false; |
922 if (lookup->IsFound() && lookup->IsCacheable()) { | 922 if (lookup->IsFound() && lookup->IsCacheable()) { |
923 if (lookup->IsField()) { | 923 if (lookup->IsField()) { |
924 compile_followup_inline = true; | 924 compile_followup_inline = true; |
925 } else if (lookup->type() == CALLBACKS && | 925 } else if (lookup->type() == CALLBACKS && |
926 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 926 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
927 Handle<ExecutableAccessorInfo> callback( | 927 Handle<ExecutableAccessorInfo> callback( |
928 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 928 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
929 compile_followup_inline = | 929 compile_followup_inline = |
930 callback->getter() != NULL && | 930 callback->getter() != NULL && |
931 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 931 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
932 type()); | 932 type()); |
933 } | 933 } |
934 } | 934 } |
935 | 935 |
936 if (compile_followup_inline) { | 936 if (compile_followup_inline) { |
937 // Compile the interceptor call, followed by inline code to load the | 937 // Compile the interceptor call, followed by inline code to load the |
938 // property from further up the prototype chain if the call fails. | 938 // property from further up the prototype chain if the call fails. |
939 // Check that the maps haven't changed. | 939 // Check that the maps haven't changed. |
940 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 940 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
941 | 941 |
942 // Preserve the receiver register explicitly whenever it is different from | 942 // Preserve the receiver register explicitly whenever it is different from |
943 // the holder and it is needed should the interceptor return without any | 943 // the holder and it is needed should the interceptor return without any |
944 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 944 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
945 // the FIELD case might cause a miss during the prototype check. | 945 // the FIELD case might cause a miss during the prototype check. |
946 bool must_perfrom_prototype_check = *holder() != lookup->holder(); | 946 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
947 bool must_preserve_receiver_reg = !receiver().Is(holder_reg) && | 947 bool must_preserve_receiver_reg = !receiver().Is(holder_reg) && |
948 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 948 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
949 | 949 |
950 // Save necessary data before invoking an interceptor. | 950 // Save necessary data before invoking an interceptor. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 } | 996 } |
997 | 997 |
998 | 998 |
999 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 999 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1000 Handle<JSObject> object, Handle<Name> name, | 1000 Handle<JSObject> object, Handle<Name> name, |
1001 Handle<ExecutableAccessorInfo> callback) { | 1001 Handle<ExecutableAccessorInfo> callback) { |
1002 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); | 1002 ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreCallback"); |
1003 Register holder_reg = Frontend(receiver(), name); | 1003 Register holder_reg = Frontend(receiver(), name); |
1004 | 1004 |
1005 // Stub never generated for non-global objects that require access checks. | 1005 // Stub never generated for non-global objects that require access checks. |
1006 ASSERT(holder()->IsJSGlobalProxy() || !holder()->IsAccessCheckNeeded()); | 1006 DCHECK(holder()->IsJSGlobalProxy() || !holder()->IsAccessCheckNeeded()); |
1007 | 1007 |
1008 // receiver() and holder_reg can alias. | 1008 // receiver() and holder_reg can alias. |
1009 ASSERT(!AreAliased(receiver(), scratch1(), scratch2(), value())); | 1009 DCHECK(!AreAliased(receiver(), scratch1(), scratch2(), value())); |
1010 ASSERT(!AreAliased(holder_reg, scratch1(), scratch2(), value())); | 1010 DCHECK(!AreAliased(holder_reg, scratch1(), scratch2(), value())); |
1011 __ Mov(scratch1(), Operand(callback)); | 1011 __ Mov(scratch1(), Operand(callback)); |
1012 __ Mov(scratch2(), Operand(name)); | 1012 __ Mov(scratch2(), Operand(name)); |
1013 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); | 1013 __ Push(receiver(), holder_reg, scratch1(), scratch2(), value()); |
1014 | 1014 |
1015 // Do tail-call to the runtime system. | 1015 // Do tail-call to the runtime system. |
1016 ExternalReference store_callback_property = | 1016 ExternalReference store_callback_property = |
1017 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1017 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
1018 __ TailCallExternalReference(store_callback_property, 5, 1); | 1018 __ TailCallExternalReference(store_callback_property, 5, 1); |
1019 | 1019 |
1020 // Return the generated code. | 1020 // Return the generated code. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 Register name = LoadIC::NameRegister(); | 1103 Register name = LoadIC::NameRegister(); |
1104 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; | 1104 static Register registers[] = { receiver, name, x3, x0, x4, x5 }; |
1105 return registers; | 1105 return registers; |
1106 } | 1106 } |
1107 | 1107 |
1108 | 1108 |
1109 Register* PropertyAccessCompiler::store_calling_convention() { | 1109 Register* PropertyAccessCompiler::store_calling_convention() { |
1110 // receiver, value, scratch1, scratch2, scratch3. | 1110 // receiver, value, scratch1, scratch2, scratch3. |
1111 Register receiver = StoreIC::ReceiverRegister(); | 1111 Register receiver = StoreIC::ReceiverRegister(); |
1112 Register name = StoreIC::NameRegister(); | 1112 Register name = StoreIC::NameRegister(); |
1113 ASSERT(x3.is(KeyedStoreIC::MapRegister())); | 1113 DCHECK(x3.is(KeyedStoreIC::MapRegister())); |
1114 static Register registers[] = { receiver, name, x3, x4, x5 }; | 1114 static Register registers[] = { receiver, name, x3, x4, x5 }; |
1115 return registers; | 1115 return registers; |
1116 } | 1116 } |
1117 | 1117 |
1118 | 1118 |
1119 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 1119 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
1120 | 1120 |
1121 | 1121 |
1122 #undef __ | 1122 #undef __ |
1123 #define __ ACCESS_MASM(masm) | 1123 #define __ ACCESS_MASM(masm) |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); | 1200 __ CompareAndBranch(this->name(), Operand(name), ne, &miss); |
1201 } | 1201 } |
1202 } | 1202 } |
1203 | 1203 |
1204 Label number_case; | 1204 Label number_case; |
1205 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1205 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
1206 __ JumpIfSmi(receiver(), smi_target); | 1206 __ JumpIfSmi(receiver(), smi_target); |
1207 | 1207 |
1208 // Polymorphic keyed stores may use the map register | 1208 // Polymorphic keyed stores may use the map register |
1209 Register map_reg = scratch1(); | 1209 Register map_reg = scratch1(); |
1210 ASSERT(kind() != Code::KEYED_STORE_IC || | 1210 DCHECK(kind() != Code::KEYED_STORE_IC || |
1211 map_reg.is(KeyedStoreIC::MapRegister())); | 1211 map_reg.is(KeyedStoreIC::MapRegister())); |
1212 __ Ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 1212 __ Ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
1213 int receiver_count = types->length(); | 1213 int receiver_count = types->length(); |
1214 int number_of_handled_maps = 0; | 1214 int number_of_handled_maps = 0; |
1215 for (int current = 0; current < receiver_count; ++current) { | 1215 for (int current = 0; current < receiver_count; ++current) { |
1216 Handle<HeapType> type = types->at(current); | 1216 Handle<HeapType> type = types->at(current); |
1217 Handle<Map> map = IC::TypeToMap(*type, isolate()); | 1217 Handle<Map> map = IC::TypeToMap(*type, isolate()); |
1218 if (!map->is_deprecated()) { | 1218 if (!map->is_deprecated()) { |
1219 number_of_handled_maps++; | 1219 number_of_handled_maps++; |
1220 Label try_next; | 1220 Label try_next; |
1221 __ Cmp(map_reg, Operand(map)); | 1221 __ Cmp(map_reg, Operand(map)); |
1222 __ B(ne, &try_next); | 1222 __ B(ne, &try_next); |
1223 if (type->Is(HeapType::Number())) { | 1223 if (type->Is(HeapType::Number())) { |
1224 ASSERT(!number_case.is_unused()); | 1224 DCHECK(!number_case.is_unused()); |
1225 __ Bind(&number_case); | 1225 __ Bind(&number_case); |
1226 } | 1226 } |
1227 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET); | 1227 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET); |
1228 __ Bind(&try_next); | 1228 __ Bind(&try_next); |
1229 } | 1229 } |
1230 } | 1230 } |
1231 ASSERT(number_of_handled_maps != 0); | 1231 DCHECK(number_of_handled_maps != 0); |
1232 | 1232 |
1233 __ Bind(&miss); | 1233 __ Bind(&miss); |
1234 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1234 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1235 | 1235 |
1236 // Return the generated code. | 1236 // Return the generated code. |
1237 InlineCacheState state = | 1237 InlineCacheState state = |
1238 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; | 1238 (number_of_handled_maps > 1) ? POLYMORPHIC : MONOMORPHIC; |
1239 return GetCode(kind(), type, name, state); | 1239 return GetCode(kind(), type, name, state); |
1240 } | 1240 } |
1241 | 1241 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 #define __ ACCESS_MASM(masm) | 1276 #define __ ACCESS_MASM(masm) |
1277 | 1277 |
1278 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | 1278 void ElementHandlerCompiler::GenerateLoadDictionaryElement( |
1279 MacroAssembler* masm) { | 1279 MacroAssembler* masm) { |
1280 // The return address is in lr. | 1280 // The return address is in lr. |
1281 Label slow, miss; | 1281 Label slow, miss; |
1282 | 1282 |
1283 Register result = x0; | 1283 Register result = x0; |
1284 Register key = LoadIC::NameRegister(); | 1284 Register key = LoadIC::NameRegister(); |
1285 Register receiver = LoadIC::ReceiverRegister(); | 1285 Register receiver = LoadIC::ReceiverRegister(); |
1286 ASSERT(receiver.is(x1)); | 1286 DCHECK(receiver.is(x1)); |
1287 ASSERT(key.is(x2)); | 1287 DCHECK(key.is(x2)); |
1288 | 1288 |
1289 __ JumpIfNotSmi(key, &miss); | 1289 __ JumpIfNotSmi(key, &miss); |
1290 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1290 __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
1291 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); | 1291 __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6); |
1292 __ Ret(); | 1292 __ Ret(); |
1293 | 1293 |
1294 __ Bind(&slow); | 1294 __ Bind(&slow); |
1295 __ IncrementCounter( | 1295 __ IncrementCounter( |
1296 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); | 1296 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3); |
1297 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | 1297 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
1298 | 1298 |
1299 // Miss case, call the runtime. | 1299 // Miss case, call the runtime. |
1300 __ Bind(&miss); | 1300 __ Bind(&miss); |
1301 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1301 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1302 } | 1302 } |
1303 | 1303 |
1304 | 1304 |
1305 } } // namespace v8::internal | 1305 } } // namespace v8::internal |
1306 | 1306 |
1307 #endif // V8_TARGET_ARCH_ARM64 | 1307 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |