OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 Register offset_scratch) { | 29 Register offset_scratch) { |
30 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); | 30 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); |
31 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); | 31 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
32 ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); | 32 ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); |
33 | 33 |
34 uint64_t key_off_addr = reinterpret_cast<uint64_t>(key_offset.address()); | 34 uint64_t key_off_addr = reinterpret_cast<uint64_t>(key_offset.address()); |
35 uint64_t value_off_addr = reinterpret_cast<uint64_t>(value_offset.address()); | 35 uint64_t value_off_addr = reinterpret_cast<uint64_t>(value_offset.address()); |
36 uint64_t map_off_addr = reinterpret_cast<uint64_t>(map_offset.address()); | 36 uint64_t map_off_addr = reinterpret_cast<uint64_t>(map_offset.address()); |
37 | 37 |
38 // Check the relative positions of the address fields. | 38 // Check the relative positions of the address fields. |
39 ASSERT(value_off_addr > key_off_addr); | 39 DCHECK(value_off_addr > key_off_addr); |
40 ASSERT((value_off_addr - key_off_addr) % 4 == 0); | 40 DCHECK((value_off_addr - key_off_addr) % 4 == 0); |
41 ASSERT((value_off_addr - key_off_addr) < (256 * 4)); | 41 DCHECK((value_off_addr - key_off_addr) < (256 * 4)); |
42 ASSERT(map_off_addr > key_off_addr); | 42 DCHECK(map_off_addr > key_off_addr); |
43 ASSERT((map_off_addr - key_off_addr) % 4 == 0); | 43 DCHECK((map_off_addr - key_off_addr) % 4 == 0); |
44 ASSERT((map_off_addr - key_off_addr) < (256 * 4)); | 44 DCHECK((map_off_addr - key_off_addr) < (256 * 4)); |
45 | 45 |
46 Label miss; | 46 Label miss; |
47 Register base_addr = scratch; | 47 Register base_addr = scratch; |
48 scratch = no_reg; | 48 scratch = no_reg; |
49 | 49 |
50 // Multiply by 3 because there are 3 fields per entry (name, code, map). | 50 // Multiply by 3 because there are 3 fields per entry (name, code, map). |
51 __ dsll(offset_scratch, offset, 1); | 51 __ dsll(offset_scratch, offset, 1); |
52 __ Daddu(offset_scratch, offset_scratch, offset); | 52 __ Daddu(offset_scratch, offset_scratch, offset); |
53 | 53 |
54 // Calculate the base address of the entry. | 54 // Calculate the base address of the entry. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 __ Jump(at); | 90 __ Jump(at); |
91 | 91 |
92 // Miss: fall through. | 92 // Miss: fall through. |
93 __ bind(&miss); | 93 __ bind(&miss); |
94 } | 94 } |
95 | 95 |
96 | 96 |
97 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 97 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
98 MacroAssembler* masm, Label* miss_label, Register receiver, | 98 MacroAssembler* masm, Label* miss_label, Register receiver, |
99 Handle<Name> name, Register scratch0, Register scratch1) { | 99 Handle<Name> name, Register scratch0, Register scratch1) { |
100 ASSERT(name->IsUniqueName()); | 100 DCHECK(name->IsUniqueName()); |
101 ASSERT(!receiver.is(scratch0)); | 101 DCHECK(!receiver.is(scratch0)); |
102 Counters* counters = masm->isolate()->counters(); | 102 Counters* counters = masm->isolate()->counters(); |
103 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 103 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
104 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 104 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
105 | 105 |
106 Label done; | 106 Label done; |
107 | 107 |
108 const int kInterceptorOrAccessCheckNeededMask = | 108 const int kInterceptorOrAccessCheckNeededMask = |
109 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 109 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
110 | 110 |
111 // Bail out if the receiver has a named interceptor or requires access checks. | 111 // Bail out if the receiver has a named interceptor or requires access checks. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 Register name, | 150 Register name, |
151 Register scratch, | 151 Register scratch, |
152 Register extra, | 152 Register extra, |
153 Register extra2, | 153 Register extra2, |
154 Register extra3) { | 154 Register extra3) { |
155 Isolate* isolate = masm->isolate(); | 155 Isolate* isolate = masm->isolate(); |
156 Label miss; | 156 Label miss; |
157 | 157 |
158 // Make sure that code is valid. The multiplying code relies on the | 158 // Make sure that code is valid. The multiplying code relies on the |
159 // entry size being 12. | 159 // entry size being 12. |
160 // ASSERT(sizeof(Entry) == 12); | 160 // DCHECK(sizeof(Entry) == 12); |
161 // ASSERT(sizeof(Entry) == 3 * kPointerSize); | 161 // DCHECK(sizeof(Entry) == 3 * kPointerSize); |
162 | 162 |
163 // Make sure the flags does not name a specific type. | 163 // Make sure the flags does not name a specific type. |
164 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 164 DCHECK(Code::ExtractTypeFromFlags(flags) == 0); |
165 | 165 |
166 // Make sure that there are no register conflicts. | 166 // Make sure that there are no register conflicts. |
167 ASSERT(!scratch.is(receiver)); | 167 DCHECK(!scratch.is(receiver)); |
168 ASSERT(!scratch.is(name)); | 168 DCHECK(!scratch.is(name)); |
169 ASSERT(!extra.is(receiver)); | 169 DCHECK(!extra.is(receiver)); |
170 ASSERT(!extra.is(name)); | 170 DCHECK(!extra.is(name)); |
171 ASSERT(!extra.is(scratch)); | 171 DCHECK(!extra.is(scratch)); |
172 ASSERT(!extra2.is(receiver)); | 172 DCHECK(!extra2.is(receiver)); |
173 ASSERT(!extra2.is(name)); | 173 DCHECK(!extra2.is(name)); |
174 ASSERT(!extra2.is(scratch)); | 174 DCHECK(!extra2.is(scratch)); |
175 ASSERT(!extra2.is(extra)); | 175 DCHECK(!extra2.is(extra)); |
176 | 176 |
177 // Check register validity. | 177 // Check register validity. |
178 ASSERT(!scratch.is(no_reg)); | 178 DCHECK(!scratch.is(no_reg)); |
179 ASSERT(!extra.is(no_reg)); | 179 DCHECK(!extra.is(no_reg)); |
180 ASSERT(!extra2.is(no_reg)); | 180 DCHECK(!extra2.is(no_reg)); |
181 ASSERT(!extra3.is(no_reg)); | 181 DCHECK(!extra3.is(no_reg)); |
182 | 182 |
183 Counters* counters = masm->isolate()->counters(); | 183 Counters* counters = masm->isolate()->counters(); |
184 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, | 184 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, |
185 extra2, extra3); | 185 extra2, extra3); |
186 | 186 |
187 // Check that the receiver isn't a smi. | 187 // Check that the receiver isn't a smi. |
188 __ JumpIfSmi(receiver, &miss); | 188 __ JumpIfSmi(receiver, &miss); |
189 | 189 |
190 // Get the map of the receiver and compute the hash. | 190 // Get the map of the receiver and compute the hash. |
191 __ ld(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); | 191 __ ld(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 266 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
267 __ Ret(USE_DELAY_SLOT); | 267 __ Ret(USE_DELAY_SLOT); |
268 __ mov(v0, scratch1); | 268 __ mov(v0, scratch1); |
269 } | 269 } |
270 | 270 |
271 | 271 |
272 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 272 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
273 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 273 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
274 Register scratch, Label* miss) { | 274 Register scratch, Label* miss) { |
275 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 275 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
276 ASSERT(cell->value()->IsTheHole()); | 276 DCHECK(cell->value()->IsTheHole()); |
277 __ li(scratch, Operand(cell)); | 277 __ li(scratch, Operand(cell)); |
278 __ ld(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 278 __ ld(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
279 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 279 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
280 __ Branch(miss, ne, scratch, Operand(at)); | 280 __ Branch(miss, ne, scratch, Operand(at)); |
281 } | 281 } |
282 | 282 |
283 | 283 |
284 // Generate StoreTransition code, value is passed in a0 register. | 284 // Generate StoreTransition code, value is passed in a0 register. |
285 // After executing generated code, the receiver_reg and name_reg | 285 // After executing generated code, the receiver_reg and name_reg |
286 // may be clobbered. | 286 // may be clobbered. |
287 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 287 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
288 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, | 288 MacroAssembler* masm, LookupResult* lookup, Handle<Map> transition, |
289 Handle<Name> name, Register receiver_reg, Register storage_reg, | 289 Handle<Name> name, Register receiver_reg, Register storage_reg, |
290 Register value_reg, Register scratch1, Register scratch2, Register scratch3, | 290 Register value_reg, Register scratch1, Register scratch2, Register scratch3, |
291 Label* miss_label, Label* slow) { | 291 Label* miss_label, Label* slow) { |
292 // a0 : value. | 292 // a0 : value. |
293 Label exit; | 293 Label exit; |
294 | 294 |
295 int descriptor = transition->LastAdded(); | 295 int descriptor = transition->LastAdded(); |
296 DescriptorArray* descriptors = transition->instance_descriptors(); | 296 DescriptorArray* descriptors = transition->instance_descriptors(); |
297 PropertyDetails details = descriptors->GetDetails(descriptor); | 297 PropertyDetails details = descriptors->GetDetails(descriptor); |
298 Representation representation = details.representation(); | 298 Representation representation = details.representation(); |
299 ASSERT(!representation.IsNone()); | 299 DCHECK(!representation.IsNone()); |
300 | 300 |
301 if (details.type() == CONSTANT) { | 301 if (details.type() == CONSTANT) { |
302 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 302 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
303 __ li(scratch1, constant); | 303 __ li(scratch1, constant); |
304 __ Branch(miss_label, ne, value_reg, Operand(scratch1)); | 304 __ Branch(miss_label, ne, value_reg, Operand(scratch1)); |
305 } else if (representation.IsSmi()) { | 305 } else if (representation.IsSmi()) { |
306 __ JumpIfNotSmi(value_reg, miss_label); | 306 __ JumpIfNotSmi(value_reg, miss_label); |
307 } else if (representation.IsHeapObject()) { | 307 } else if (representation.IsHeapObject()) { |
308 __ JumpIfSmi(value_reg, miss_label); | 308 __ JumpIfSmi(value_reg, miss_label); |
309 HeapType* field_type = descriptors->GetFieldType(descriptor); | 309 HeapType* field_type = descriptors->GetFieldType(descriptor); |
(...skipping 29 matching lines...) Expand all Loading... |
339 __ bind(&heap_number); | 339 __ bind(&heap_number); |
340 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, | 340 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, |
341 miss_label, DONT_DO_SMI_CHECK); | 341 miss_label, DONT_DO_SMI_CHECK); |
342 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 342 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
343 | 343 |
344 __ bind(&do_store); | 344 __ bind(&do_store); |
345 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); | 345 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); |
346 } | 346 } |
347 | 347 |
348 // Stub never generated for objects that require access checks. | 348 // Stub never generated for objects that require access checks. |
349 ASSERT(!transition->is_access_check_needed()); | 349 DCHECK(!transition->is_access_check_needed()); |
350 | 350 |
351 // Perform map transition for the receiver if necessary. | 351 // Perform map transition for the receiver if necessary. |
352 if (details.type() == FIELD && | 352 if (details.type() == FIELD && |
353 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 353 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
354 // The properties must be extended before we can store the value. | 354 // The properties must be extended before we can store the value. |
355 // We jump to a runtime call that extends the properties array. | 355 // We jump to a runtime call that extends the properties array. |
356 __ push(receiver_reg); | 356 __ push(receiver_reg); |
357 __ li(a2, Operand(transition)); | 357 __ li(a2, Operand(transition)); |
358 __ Push(a2, a0); | 358 __ Push(a2, a0); |
359 __ TailCallExternalReference( | 359 __ TailCallExternalReference( |
(...skipping 11 matching lines...) Expand all Loading... |
371 __ RecordWriteField(receiver_reg, | 371 __ RecordWriteField(receiver_reg, |
372 HeapObject::kMapOffset, | 372 HeapObject::kMapOffset, |
373 scratch1, | 373 scratch1, |
374 scratch2, | 374 scratch2, |
375 kRAHasNotBeenSaved, | 375 kRAHasNotBeenSaved, |
376 kDontSaveFPRegs, | 376 kDontSaveFPRegs, |
377 OMIT_REMEMBERED_SET, | 377 OMIT_REMEMBERED_SET, |
378 OMIT_SMI_CHECK); | 378 OMIT_SMI_CHECK); |
379 | 379 |
380 if (details.type() == CONSTANT) { | 380 if (details.type() == CONSTANT) { |
381 ASSERT(value_reg.is(a0)); | 381 DCHECK(value_reg.is(a0)); |
382 __ Ret(USE_DELAY_SLOT); | 382 __ Ret(USE_DELAY_SLOT); |
383 __ mov(v0, a0); | 383 __ mov(v0, a0); |
384 return; | 384 return; |
385 } | 385 } |
386 | 386 |
387 int index = transition->instance_descriptors()->GetFieldIndex( | 387 int index = transition->instance_descriptors()->GetFieldIndex( |
388 transition->LastAdded()); | 388 transition->LastAdded()); |
389 | 389 |
390 // Adjust for the number of properties stored in the object. Even in the | 390 // Adjust for the number of properties stored in the object. Even in the |
391 // face of a transition we can use the old map here because the size of the | 391 // face of a transition we can use the old map here because the size of the |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 storage_reg, | 440 storage_reg, |
441 receiver_reg, | 441 receiver_reg, |
442 kRAHasNotBeenSaved, | 442 kRAHasNotBeenSaved, |
443 kDontSaveFPRegs, | 443 kDontSaveFPRegs, |
444 EMIT_REMEMBERED_SET, | 444 EMIT_REMEMBERED_SET, |
445 smi_check); | 445 smi_check); |
446 } | 446 } |
447 } | 447 } |
448 | 448 |
449 // Return the value (register v0). | 449 // Return the value (register v0). |
450 ASSERT(value_reg.is(a0)); | 450 DCHECK(value_reg.is(a0)); |
451 __ bind(&exit); | 451 __ bind(&exit); |
452 __ Ret(USE_DELAY_SLOT); | 452 __ Ret(USE_DELAY_SLOT); |
453 __ mov(v0, a0); | 453 __ mov(v0, a0); |
454 } | 454 } |
455 | 455 |
456 | 456 |
457 // Generate StoreField code, value is passed in a0 register. | 457 // Generate StoreField code, value is passed in a0 register. |
458 // When leaving generated code after success, the receiver_reg and name_reg | 458 // When leaving generated code after success, the receiver_reg and name_reg |
459 // may be clobbered. Upon branch to miss_label, the receiver and name | 459 // may be clobbered. Upon branch to miss_label, the receiver and name |
460 // registers have their original values. | 460 // registers have their original values. |
461 void NamedStoreHandlerCompiler::GenerateStoreField( | 461 void NamedStoreHandlerCompiler::GenerateStoreField( |
462 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, | 462 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
463 Register receiver_reg, Register name_reg, Register value_reg, | 463 Register receiver_reg, Register name_reg, Register value_reg, |
464 Register scratch1, Register scratch2, Label* miss_label) { | 464 Register scratch1, Register scratch2, Label* miss_label) { |
465 // a0 : value | 465 // a0 : value |
466 Label exit; | 466 Label exit; |
467 | 467 |
468 // Stub never generated for non-global objects that require access | 468 // Stub never generated for non-global objects that require access |
469 // checks. | 469 // checks. |
470 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 470 DCHECK(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
471 | 471 |
472 FieldIndex index = lookup->GetFieldIndex(); | 472 FieldIndex index = lookup->GetFieldIndex(); |
473 | 473 |
474 Representation representation = lookup->representation(); | 474 Representation representation = lookup->representation(); |
475 ASSERT(!representation.IsNone()); | 475 DCHECK(!representation.IsNone()); |
476 if (representation.IsSmi()) { | 476 if (representation.IsSmi()) { |
477 __ JumpIfNotSmi(value_reg, miss_label); | 477 __ JumpIfNotSmi(value_reg, miss_label); |
478 } else if (representation.IsHeapObject()) { | 478 } else if (representation.IsHeapObject()) { |
479 __ JumpIfSmi(value_reg, miss_label); | 479 __ JumpIfSmi(value_reg, miss_label); |
480 HeapType* field_type = lookup->GetFieldType(); | 480 HeapType* field_type = lookup->GetFieldType(); |
481 HeapType::Iterator<Map> it = field_type->Classes(); | 481 HeapType::Iterator<Map> it = field_type->Classes(); |
482 if (!it.Done()) { | 482 if (!it.Done()) { |
483 __ ld(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 483 __ ld(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
484 Label do_store; | 484 Label do_store; |
485 Handle<Map> current; | 485 Handle<Map> current; |
(...skipping 28 matching lines...) Expand all Loading... |
514 __ jmp(&do_store); | 514 __ jmp(&do_store); |
515 | 515 |
516 __ bind(&heap_number); | 516 __ bind(&heap_number); |
517 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, | 517 __ CheckMap(value_reg, scratch2, Heap::kHeapNumberMapRootIndex, |
518 miss_label, DONT_DO_SMI_CHECK); | 518 miss_label, DONT_DO_SMI_CHECK); |
519 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); | 519 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); |
520 | 520 |
521 __ bind(&do_store); | 521 __ bind(&do_store); |
522 __ sdc1(f4, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); | 522 __ sdc1(f4, FieldMemOperand(scratch1, HeapNumber::kValueOffset)); |
523 // Return the value (register v0). | 523 // Return the value (register v0). |
524 ASSERT(value_reg.is(a0)); | 524 DCHECK(value_reg.is(a0)); |
525 __ Ret(USE_DELAY_SLOT); | 525 __ Ret(USE_DELAY_SLOT); |
526 __ mov(v0, a0); | 526 __ mov(v0, a0); |
527 return; | 527 return; |
528 } | 528 } |
529 | 529 |
530 // TODO(verwaest): Share this code as a code stub. | 530 // TODO(verwaest): Share this code as a code stub. |
531 SmiCheck smi_check = representation.IsTagged() | 531 SmiCheck smi_check = representation.IsTagged() |
532 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 532 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
533 if (index.is_inobject()) { | 533 if (index.is_inobject()) { |
534 // Set the property straight into the object. | 534 // Set the property straight into the object. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 name_reg, | 569 name_reg, |
570 receiver_reg, | 570 receiver_reg, |
571 kRAHasNotBeenSaved, | 571 kRAHasNotBeenSaved, |
572 kDontSaveFPRegs, | 572 kDontSaveFPRegs, |
573 EMIT_REMEMBERED_SET, | 573 EMIT_REMEMBERED_SET, |
574 smi_check); | 574 smi_check); |
575 } | 575 } |
576 } | 576 } |
577 | 577 |
578 // Return the value (register v0). | 578 // Return the value (register v0). |
579 ASSERT(value_reg.is(a0)); | 579 DCHECK(value_reg.is(a0)); |
580 __ bind(&exit); | 580 __ bind(&exit); |
581 __ Ret(USE_DELAY_SLOT); | 581 __ Ret(USE_DELAY_SLOT); |
582 __ mov(v0, a0); | 582 __ mov(v0, a0); |
583 } | 583 } |
584 | 584 |
585 | 585 |
586 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, | 586 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
587 Label* label, | 587 Label* label, |
588 Handle<Name> name) { | 588 Handle<Name> name) { |
589 if (!label->is_unused()) { | 589 if (!label->is_unused()) { |
590 __ bind(label); | 590 __ bind(label); |
591 __ li(this->name(), Operand(name)); | 591 __ li(this->name(), Operand(name)); |
592 } | 592 } |
593 } | 593 } |
594 | 594 |
595 | 595 |
596 static void PushInterceptorArguments(MacroAssembler* masm, | 596 static void PushInterceptorArguments(MacroAssembler* masm, |
597 Register receiver, | 597 Register receiver, |
598 Register holder, | 598 Register holder, |
599 Register name, | 599 Register name, |
600 Handle<JSObject> holder_obj) { | 600 Handle<JSObject> holder_obj) { |
601 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 601 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
602 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 602 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); |
603 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 603 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); |
604 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 604 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); |
605 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | 605 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); |
606 __ push(name); | 606 __ push(name); |
607 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 607 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
608 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 608 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
609 Register scratch = name; | 609 Register scratch = name; |
610 __ li(scratch, Operand(interceptor)); | 610 __ li(scratch, Operand(interceptor)); |
611 __ Push(scratch, receiver, holder); | 611 __ Push(scratch, receiver, holder); |
612 } | 612 } |
613 | 613 |
614 | 614 |
615 static void CompileCallLoadPropertyWithInterceptor( | 615 static void CompileCallLoadPropertyWithInterceptor( |
616 MacroAssembler* masm, | 616 MacroAssembler* masm, |
617 Register receiver, | 617 Register receiver, |
618 Register holder, | 618 Register holder, |
619 Register name, | 619 Register name, |
620 Handle<JSObject> holder_obj, | 620 Handle<JSObject> holder_obj, |
621 IC::UtilityId id) { | 621 IC::UtilityId id) { |
622 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 622 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
623 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | 623 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |
624 NamedLoadHandlerCompiler::kInterceptorArgsLength); | 624 NamedLoadHandlerCompiler::kInterceptorArgsLength); |
625 } | 625 } |
626 | 626 |
627 | 627 |
628 // Generate call to api function. | 628 // Generate call to api function. |
629 void PropertyHandlerCompiler::GenerateFastApiCall( | 629 void PropertyHandlerCompiler::GenerateFastApiCall( |
630 MacroAssembler* masm, const CallOptimization& optimization, | 630 MacroAssembler* masm, const CallOptimization& optimization, |
631 Handle<Map> receiver_map, Register receiver, Register scratch_in, | 631 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
632 bool is_store, int argc, Register* values) { | 632 bool is_store, int argc, Register* values) { |
633 ASSERT(!receiver.is(scratch_in)); | 633 DCHECK(!receiver.is(scratch_in)); |
634 // Preparing to push, adjust sp. | 634 // Preparing to push, adjust sp. |
635 __ Dsubu(sp, sp, Operand((argc + 1) * kPointerSize)); | 635 __ Dsubu(sp, sp, Operand((argc + 1) * kPointerSize)); |
636 __ sd(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver. | 636 __ sd(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver. |
637 // Write the arguments to stack frame. | 637 // Write the arguments to stack frame. |
638 for (int i = 0; i < argc; i++) { | 638 for (int i = 0; i < argc; i++) { |
639 Register arg = values[argc-1-i]; | 639 Register arg = values[argc-1-i]; |
640 ASSERT(!receiver.is(arg)); | 640 DCHECK(!receiver.is(arg)); |
641 ASSERT(!scratch_in.is(arg)); | 641 DCHECK(!scratch_in.is(arg)); |
642 __ sd(arg, MemOperand(sp, (argc-1-i) * kPointerSize)); // Push arg. | 642 __ sd(arg, MemOperand(sp, (argc-1-i) * kPointerSize)); // Push arg. |
643 } | 643 } |
644 ASSERT(optimization.is_simple_api_call()); | 644 DCHECK(optimization.is_simple_api_call()); |
645 | 645 |
646 // Abi for CallApiFunctionStub. | 646 // Abi for CallApiFunctionStub. |
647 Register callee = a0; | 647 Register callee = a0; |
648 Register call_data = a4; | 648 Register call_data = a4; |
649 Register holder = a2; | 649 Register holder = a2; |
650 Register api_function_address = a1; | 650 Register api_function_address = a1; |
651 | 651 |
652 // Put holder in place. | 652 // Put holder in place. |
653 CallOptimization::HolderLookup holder_lookup; | 653 CallOptimization::HolderLookup holder_lookup; |
654 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 654 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 #define __ ACCESS_MASM(masm()) | 711 #define __ ACCESS_MASM(masm()) |
712 | 712 |
713 | 713 |
714 Register PropertyHandlerCompiler::CheckPrototypes( | 714 Register PropertyHandlerCompiler::CheckPrototypes( |
715 Register object_reg, Register holder_reg, Register scratch1, | 715 Register object_reg, Register holder_reg, Register scratch1, |
716 Register scratch2, Handle<Name> name, Label* miss, | 716 Register scratch2, Handle<Name> name, Label* miss, |
717 PrototypeCheckType check) { | 717 PrototypeCheckType check) { |
718 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 718 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
719 | 719 |
720 // Make sure there's no overlap between holder and object registers. | 720 // Make sure there's no overlap between holder and object registers. |
721 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 721 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
722 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 722 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
723 && !scratch2.is(scratch1)); | 723 && !scratch2.is(scratch1)); |
724 | 724 |
725 // Keep track of the current object in register reg. | 725 // Keep track of the current object in register reg. |
726 Register reg = object_reg; | 726 Register reg = object_reg; |
727 int depth = 0; | 727 int depth = 0; |
728 | 728 |
729 Handle<JSObject> current = Handle<JSObject>::null(); | 729 Handle<JSObject> current = Handle<JSObject>::null(); |
730 if (type()->IsConstant()) { | 730 if (type()->IsConstant()) { |
731 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 731 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
732 } | 732 } |
733 Handle<JSObject> prototype = Handle<JSObject>::null(); | 733 Handle<JSObject> prototype = Handle<JSObject>::null(); |
734 Handle<Map> current_map = receiver_map; | 734 Handle<Map> current_map = receiver_map; |
735 Handle<Map> holder_map(holder()->map()); | 735 Handle<Map> holder_map(holder()->map()); |
736 // Traverse the prototype chain and check the maps in the prototype chain for | 736 // Traverse the prototype chain and check the maps in the prototype chain for |
737 // fast and global objects or do negative lookup for normal objects. | 737 // fast and global objects or do negative lookup for normal objects. |
738 while (!current_map.is_identical_to(holder_map)) { | 738 while (!current_map.is_identical_to(holder_map)) { |
739 ++depth; | 739 ++depth; |
740 | 740 |
741 // Only global objects and objects that do not require access | 741 // Only global objects and objects that do not require access |
742 // checks are allowed in stubs. | 742 // checks are allowed in stubs. |
743 ASSERT(current_map->IsJSGlobalProxyMap() || | 743 DCHECK(current_map->IsJSGlobalProxyMap() || |
744 !current_map->is_access_check_needed()); | 744 !current_map->is_access_check_needed()); |
745 | 745 |
746 prototype = handle(JSObject::cast(current_map->prototype())); | 746 prototype = handle(JSObject::cast(current_map->prototype())); |
747 if (current_map->is_dictionary_map() && | 747 if (current_map->is_dictionary_map() && |
748 !current_map->IsJSGlobalObjectMap() && | 748 !current_map->IsJSGlobalObjectMap() && |
749 !current_map->IsJSGlobalProxyMap()) { | 749 !current_map->IsJSGlobalProxyMap()) { |
750 if (!name->IsUniqueName()) { | 750 if (!name->IsUniqueName()) { |
751 ASSERT(name->IsString()); | 751 DCHECK(name->IsString()); |
752 name = factory()->InternalizeString(Handle<String>::cast(name)); | 752 name = factory()->InternalizeString(Handle<String>::cast(name)); |
753 } | 753 } |
754 ASSERT(current.is_null() || | 754 DCHECK(current.is_null() || |
755 current->property_dictionary()->FindEntry(name) == | 755 current->property_dictionary()->FindEntry(name) == |
756 NameDictionary::kNotFound); | 756 NameDictionary::kNotFound); |
757 | 757 |
758 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 758 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
759 scratch1, scratch2); | 759 scratch1, scratch2); |
760 | 760 |
761 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 761 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
762 reg = holder_reg; // From now on the object will be in holder_reg. | 762 reg = holder_reg; // From now on the object will be in holder_reg. |
763 __ ld(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 763 __ ld(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
764 } else { | 764 } else { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 | 803 |
804 // Log the check depth. | 804 // Log the check depth. |
805 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 805 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
806 | 806 |
807 if (depth != 0 || check == CHECK_ALL_MAPS) { | 807 if (depth != 0 || check == CHECK_ALL_MAPS) { |
808 // Check the holder map. | 808 // Check the holder map. |
809 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); | 809 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK); |
810 } | 810 } |
811 | 811 |
812 // Perform security check for access to the global object. | 812 // Perform security check for access to the global object. |
813 ASSERT(current_map->IsJSGlobalProxyMap() || | 813 DCHECK(current_map->IsJSGlobalProxyMap() || |
814 !current_map->is_access_check_needed()); | 814 !current_map->is_access_check_needed()); |
815 if (current_map->IsJSGlobalProxyMap()) { | 815 if (current_map->IsJSGlobalProxyMap()) { |
816 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 816 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
817 } | 817 } |
818 | 818 |
819 // Return the register containing the holder. | 819 // Return the register containing the holder. |
820 return reg; | 820 return reg; |
821 } | 821 } |
822 | 822 |
823 | 823 |
(...skipping 20 matching lines...) Expand all Loading... |
844 | 844 |
845 | 845 |
846 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 846 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
847 Handle<Name> name, | 847 Handle<Name> name, |
848 Handle<Object> callback) { | 848 Handle<Object> callback) { |
849 Label miss; | 849 Label miss; |
850 | 850 |
851 Register reg = FrontendHeader(object_reg, name, &miss); | 851 Register reg = FrontendHeader(object_reg, name, &miss); |
852 | 852 |
853 if (!holder()->HasFastProperties()) { | 853 if (!holder()->HasFastProperties()) { |
854 ASSERT(!holder()->IsGlobalObject()); | 854 DCHECK(!holder()->IsGlobalObject()); |
855 ASSERT(!reg.is(scratch2())); | 855 DCHECK(!reg.is(scratch2())); |
856 ASSERT(!reg.is(scratch3())); | 856 DCHECK(!reg.is(scratch3())); |
857 ASSERT(!reg.is(scratch4())); | 857 DCHECK(!reg.is(scratch4())); |
858 | 858 |
859 // Load the properties dictionary. | 859 // Load the properties dictionary. |
860 Register dictionary = scratch4(); | 860 Register dictionary = scratch4(); |
861 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 861 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
862 | 862 |
863 // Probe the dictionary. | 863 // Probe the dictionary. |
864 Label probe_done; | 864 Label probe_done; |
865 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), | 865 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), |
866 &miss, | 866 &miss, |
867 &probe_done, | 867 &probe_done, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 Register reg, Handle<ExecutableAccessorInfo> callback) { | 905 Register reg, Handle<ExecutableAccessorInfo> callback) { |
906 // Build AccessorInfo::args_ list on the stack and push property name below | 906 // Build AccessorInfo::args_ list on the stack and push property name below |
907 // the exit frame to make GC aware of them and store pointers to them. | 907 // the exit frame to make GC aware of them and store pointers to them. |
908 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 908 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
909 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 909 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
910 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 910 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
911 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 911 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
912 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 912 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
913 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 913 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
914 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 914 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |
915 ASSERT(!scratch2().is(reg)); | 915 DCHECK(!scratch2().is(reg)); |
916 ASSERT(!scratch3().is(reg)); | 916 DCHECK(!scratch3().is(reg)); |
917 ASSERT(!scratch4().is(reg)); | 917 DCHECK(!scratch4().is(reg)); |
918 __ push(receiver()); | 918 __ push(receiver()); |
919 if (heap()->InNewSpace(callback->data())) { | 919 if (heap()->InNewSpace(callback->data())) { |
920 __ li(scratch3(), callback); | 920 __ li(scratch3(), callback); |
921 __ ld(scratch3(), FieldMemOperand(scratch3(), | 921 __ ld(scratch3(), FieldMemOperand(scratch3(), |
922 ExecutableAccessorInfo::kDataOffset)); | 922 ExecutableAccessorInfo::kDataOffset)); |
923 } else { | 923 } else { |
924 __ li(scratch3(), Handle<Object>(callback->data(), isolate())); | 924 __ li(scratch3(), Handle<Object>(callback->data(), isolate())); |
925 } | 925 } |
926 __ Dsubu(sp, sp, 6 * kPointerSize); | 926 __ Dsubu(sp, sp, 6 * kPointerSize); |
927 __ sd(scratch3(), MemOperand(sp, 5 * kPointerSize)); | 927 __ sd(scratch3(), MemOperand(sp, 5 * kPointerSize)); |
(...skipping 18 matching lines...) Expand all Loading... |
946 __ li(getter_address_reg, Operand(ref)); | 946 __ li(getter_address_reg, Operand(ref)); |
947 | 947 |
948 CallApiGetterStub stub(isolate()); | 948 CallApiGetterStub stub(isolate()); |
949 __ TailCallStub(&stub); | 949 __ TailCallStub(&stub); |
950 } | 950 } |
951 | 951 |
952 | 952 |
953 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, | 953 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
954 LookupResult* lookup, | 954 LookupResult* lookup, |
955 Handle<Name> name) { | 955 Handle<Name> name) { |
956 ASSERT(holder()->HasNamedInterceptor()); | 956 DCHECK(holder()->HasNamedInterceptor()); |
957 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 957 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
958 | 958 |
959 // So far the most popular follow ups for interceptor loads are FIELD | 959 // So far the most popular follow ups for interceptor loads are FIELD |
960 // and CALLBACKS, so inline only them, other cases may be added | 960 // and CALLBACKS, so inline only them, other cases may be added |
961 // later. | 961 // later. |
962 bool compile_followup_inline = false; | 962 bool compile_followup_inline = false; |
963 if (lookup->IsFound() && lookup->IsCacheable()) { | 963 if (lookup->IsFound() && lookup->IsCacheable()) { |
964 if (lookup->IsField()) { | 964 if (lookup->IsField()) { |
965 compile_followup_inline = true; | 965 compile_followup_inline = true; |
966 } else if (lookup->type() == CALLBACKS && | 966 } else if (lookup->type() == CALLBACKS && |
967 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 967 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
968 Handle<ExecutableAccessorInfo> callback( | 968 Handle<ExecutableAccessorInfo> callback( |
969 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 969 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
970 compile_followup_inline = | 970 compile_followup_inline = |
971 callback->getter() != NULL && | 971 callback->getter() != NULL && |
972 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 972 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
973 type()); | 973 type()); |
974 } | 974 } |
975 } | 975 } |
976 | 976 |
977 if (compile_followup_inline) { | 977 if (compile_followup_inline) { |
978 // Compile the interceptor call, followed by inline code to load the | 978 // Compile the interceptor call, followed by inline code to load the |
979 // property from further up the prototype chain if the call fails. | 979 // property from further up the prototype chain if the call fails. |
980 // Check that the maps haven't changed. | 980 // Check that the maps haven't changed. |
981 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 981 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
982 | 982 |
983 // Preserve the receiver register explicitly whenever it is different from | 983 // Preserve the receiver register explicitly whenever it is different from |
984 // the holder and it is needed should the interceptor return without any | 984 // the holder and it is needed should the interceptor return without any |
985 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 985 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
986 // the FIELD case might cause a miss during the prototype check. | 986 // the FIELD case might cause a miss during the prototype check. |
987 bool must_perfrom_prototype_check = *holder() != lookup->holder(); | 987 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
988 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 988 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
989 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 989 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
990 | 990 |
991 // Save necessary data before invoking an interceptor. | 991 // Save necessary data before invoking an interceptor. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 Register name = LoadIC::NameRegister(); | 1124 Register name = LoadIC::NameRegister(); |
1125 static Register registers[] = { receiver, name, a3, a0, a4, a5 }; | 1125 static Register registers[] = { receiver, name, a3, a0, a4, a5 }; |
1126 return registers; | 1126 return registers; |
1127 } | 1127 } |
1128 | 1128 |
1129 | 1129 |
1130 Register* PropertyAccessCompiler::store_calling_convention() { | 1130 Register* PropertyAccessCompiler::store_calling_convention() { |
1131 // receiver, name, scratch1, scratch2, scratch3. | 1131 // receiver, name, scratch1, scratch2, scratch3. |
1132 Register receiver = StoreIC::ReceiverRegister(); | 1132 Register receiver = StoreIC::ReceiverRegister(); |
1133 Register name = StoreIC::NameRegister(); | 1133 Register name = StoreIC::NameRegister(); |
1134 ASSERT(a3.is(KeyedStoreIC::MapRegister())); | 1134 DCHECK(a3.is(KeyedStoreIC::MapRegister())); |
1135 static Register registers[] = { receiver, name, a3, a4, a5 }; | 1135 static Register registers[] = { receiver, name, a3, a4, a5 }; |
1136 return registers; | 1136 return registers; |
1137 } | 1137 } |
1138 | 1138 |
1139 | 1139 |
1140 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 1140 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
1141 | 1141 |
1142 | 1142 |
1143 #undef __ | 1143 #undef __ |
1144 #define __ ACCESS_MASM(masm) | 1144 #define __ ACCESS_MASM(masm) |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 } | 1231 } |
1232 } | 1232 } |
1233 | 1233 |
1234 Label number_case; | 1234 Label number_case; |
1235 Register match = scratch2(); | 1235 Register match = scratch2(); |
1236 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1236 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
1237 __ JumpIfSmi(receiver(), smi_target, match); // Reg match is 0 if Smi. | 1237 __ JumpIfSmi(receiver(), smi_target, match); // Reg match is 0 if Smi. |
1238 | 1238 |
1239 // Polymorphic keyed stores may use the map register | 1239 // Polymorphic keyed stores may use the map register |
1240 Register map_reg = scratch1(); | 1240 Register map_reg = scratch1(); |
1241 ASSERT(kind() != Code::KEYED_STORE_IC || | 1241 DCHECK(kind() != Code::KEYED_STORE_IC || |
1242 map_reg.is(KeyedStoreIC::MapRegister())); | 1242 map_reg.is(KeyedStoreIC::MapRegister())); |
1243 | 1243 |
1244 int receiver_count = types->length(); | 1244 int receiver_count = types->length(); |
1245 int number_of_handled_maps = 0; | 1245 int number_of_handled_maps = 0; |
1246 __ ld(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 1246 __ ld(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
1247 for (int current = 0; current < receiver_count; ++current) { | 1247 for (int current = 0; current < receiver_count; ++current) { |
1248 Handle<HeapType> type = types->at(current); | 1248 Handle<HeapType> type = types->at(current); |
1249 Handle<Map> map = IC::TypeToMap(*type, isolate()); | 1249 Handle<Map> map = IC::TypeToMap(*type, isolate()); |
1250 if (!map->is_deprecated()) { | 1250 if (!map->is_deprecated()) { |
1251 number_of_handled_maps++; | 1251 number_of_handled_maps++; |
1252 // Check map and tail call if there's a match. | 1252 // Check map and tail call if there's a match. |
1253 // Separate compare from branch, to provide path for above JumpIfSmi(). | 1253 // Separate compare from branch, to provide path for above JumpIfSmi(). |
1254 __ Dsubu(match, map_reg, Operand(map)); | 1254 __ Dsubu(match, map_reg, Operand(map)); |
1255 if (type->Is(HeapType::Number())) { | 1255 if (type->Is(HeapType::Number())) { |
1256 ASSERT(!number_case.is_unused()); | 1256 DCHECK(!number_case.is_unused()); |
1257 __ bind(&number_case); | 1257 __ bind(&number_case); |
1258 } | 1258 } |
1259 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, | 1259 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, |
1260 eq, match, Operand(zero_reg)); | 1260 eq, match, Operand(zero_reg)); |
1261 } | 1261 } |
1262 } | 1262 } |
1263 ASSERT(number_of_handled_maps != 0); | 1263 DCHECK(number_of_handled_maps != 0); |
1264 | 1264 |
1265 __ bind(&miss); | 1265 __ bind(&miss); |
1266 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1266 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1267 | 1267 |
1268 // Return the generated code. | 1268 // Return the generated code. |
1269 InlineCacheState state = | 1269 InlineCacheState state = |
1270 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1270 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
1271 return GetCode(kind(), type, name, state); | 1271 return GetCode(kind(), type, name, state); |
1272 } | 1272 } |
1273 | 1273 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1316 #define __ ACCESS_MASM(masm) | 1316 #define __ ACCESS_MASM(masm) |
1317 | 1317 |
1318 | 1318 |
1319 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | 1319 void ElementHandlerCompiler::GenerateLoadDictionaryElement( |
1320 MacroAssembler* masm) { | 1320 MacroAssembler* masm) { |
1321 // The return address is in ra | 1321 // The return address is in ra |
1322 Label slow, miss; | 1322 Label slow, miss; |
1323 | 1323 |
1324 Register key = LoadIC::NameRegister(); | 1324 Register key = LoadIC::NameRegister(); |
1325 Register receiver = LoadIC::ReceiverRegister(); | 1325 Register receiver = LoadIC::ReceiverRegister(); |
1326 ASSERT(receiver.is(a1)); | 1326 DCHECK(receiver.is(a1)); |
1327 ASSERT(key.is(a2)); | 1327 DCHECK(key.is(a2)); |
1328 | 1328 |
1329 __ UntagAndJumpIfNotSmi(a6, key, &miss); | 1329 __ UntagAndJumpIfNotSmi(a6, key, &miss); |
1330 __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 1330 __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
1331 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 1331 DCHECK(kSmiTagSize + kSmiShiftSize == 32); |
1332 __ LoadFromNumberDictionary(&slow, a4, key, v0, a6, a3, a5); | 1332 __ LoadFromNumberDictionary(&slow, a4, key, v0, a6, a3, a5); |
1333 __ Ret(); | 1333 __ Ret(); |
1334 | 1334 |
1335 // Slow case, key and receiver still unmodified. | 1335 // Slow case, key and receiver still unmodified. |
1336 __ bind(&slow); | 1336 __ bind(&slow); |
1337 __ IncrementCounter( | 1337 __ IncrementCounter( |
1338 masm->isolate()->counters()->keyed_load_external_array_slow(), | 1338 masm->isolate()->counters()->keyed_load_external_array_slow(), |
1339 1, a2, a3); | 1339 1, a2, a3); |
1340 | 1340 |
1341 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | 1341 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
1342 | 1342 |
1343 // Miss case, call the runtime. | 1343 // Miss case, call the runtime. |
1344 __ bind(&miss); | 1344 __ bind(&miss); |
1345 | 1345 |
1346 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1346 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1347 } | 1347 } |
1348 | 1348 |
1349 | 1349 |
1350 #undef __ | 1350 #undef __ |
1351 | 1351 |
1352 } } // namespace v8::internal | 1352 } } // namespace v8::internal |
1353 | 1353 |
1354 #endif // V8_TARGET_ARCH_MIPS64 | 1354 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |