OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 #include "src/ic/handler-compiler.h" | 7 #include "src/ic/handler-compiler.h" |
8 | 8 |
9 #include "src/api-arguments.h" | 9 #include "src/api-arguments.h" |
10 #include "src/field-type.h" | 10 #include "src/field-type.h" |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 Register object_reg, Register holder_reg, Register scratch1, | 416 Register object_reg, Register holder_reg, Register scratch1, |
417 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, | 417 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
418 ReturnHolder return_what) { | 418 ReturnHolder return_what) { |
419 Handle<Map> receiver_map = map(); | 419 Handle<Map> receiver_map = map(); |
420 | 420 |
421 // Make sure there's no overlap between holder and object registers. | 421 // Make sure there's no overlap between holder and object registers. |
422 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 422 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
423 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 423 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
424 !scratch2.is(scratch1)); | 424 !scratch2.is(scratch1)); |
425 | 425 |
426 if (FLAG_eliminate_prototype_chain_checks) { | 426 Handle<Cell> validity_cell = |
427 Handle<Cell> validity_cell = | 427 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
428 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | 428 if (!validity_cell.is_null()) { |
429 if (!validity_cell.is_null()) { | 429 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); |
430 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), | 430 __ li(scratch1, Operand(validity_cell)); |
431 validity_cell->value()); | 431 __ lw(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
432 __ li(scratch1, Operand(validity_cell)); | 432 __ Branch(miss, ne, scratch1, |
433 __ lw(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); | 433 Operand(Smi::FromInt(Map::kPrototypeChainValid))); |
434 __ Branch(miss, ne, scratch1, | 434 } |
435 Operand(Smi::FromInt(Map::kPrototypeChainValid))); | |
436 } | |
437 | 435 |
438 // The prototype chain of primitives (and their JSValue wrappers) depends | 436 // The prototype chain of primitives (and their JSValue wrappers) depends |
439 // on the native context, which can't be guarded by validity cells. | 437 // on the native context, which can't be guarded by validity cells. |
440 // |object_reg| holds the native context specific prototype in this case; | 438 // |object_reg| holds the native context specific prototype in this case; |
441 // we need to check its map. | 439 // we need to check its map. |
442 if (check == CHECK_ALL_MAPS) { | 440 if (check == CHECK_ALL_MAPS) { |
443 __ lw(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 441 __ lw(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
444 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | 442 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
445 __ GetWeakValue(scratch2, cell); | 443 __ GetWeakValue(scratch2, cell); |
446 __ Branch(miss, ne, scratch1, Operand(scratch2)); | 444 __ Branch(miss, ne, scratch1, Operand(scratch2)); |
447 } | |
448 } | 445 } |
449 | 446 |
450 // Keep track of the current object in register reg. | 447 // Keep track of the current object in register reg. |
451 Register reg = object_reg; | 448 Register reg = object_reg; |
452 int depth = 0; | 449 int depth = 0; |
453 | 450 |
454 Handle<JSObject> current = Handle<JSObject>::null(); | 451 Handle<JSObject> current = Handle<JSObject>::null(); |
455 if (receiver_map->IsJSGlobalObjectMap()) { | 452 if (receiver_map->IsJSGlobalObjectMap()) { |
456 current = isolate()->global_object(); | 453 current = isolate()->global_object(); |
457 } | 454 } |
(...skipping 15 matching lines...) Expand all Loading... |
473 // fast and global objects or do negative lookup for normal objects. | 470 // fast and global objects or do negative lookup for normal objects. |
474 while (!current_map.is_identical_to(holder_map)) { | 471 while (!current_map.is_identical_to(holder_map)) { |
475 ++depth; | 472 ++depth; |
476 | 473 |
477 // Only global objects and objects that do not require access | 474 // Only global objects and objects that do not require access |
478 // checks are allowed in stubs. | 475 // checks are allowed in stubs. |
479 DCHECK(current_map->IsJSGlobalProxyMap() || | 476 DCHECK(current_map->IsJSGlobalProxyMap() || |
480 !current_map->is_access_check_needed()); | 477 !current_map->is_access_check_needed()); |
481 | 478 |
482 prototype = handle(JSObject::cast(current_map->prototype())); | 479 prototype = handle(JSObject::cast(current_map->prototype())); |
483 if (current_map->is_dictionary_map() && | 480 if (current_map->IsJSGlobalObjectMap()) { |
484 !current_map->IsJSGlobalObjectMap()) { | 481 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
| 482 name, scratch2, miss); |
| 483 } else if (current_map->is_dictionary_map()) { |
485 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 484 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
486 if (!name->IsUniqueName()) { | 485 if (!name->IsUniqueName()) { |
487 DCHECK(name->IsString()); | 486 DCHECK(name->IsString()); |
488 name = factory()->InternalizeString(Handle<String>::cast(name)); | 487 name = factory()->InternalizeString(Handle<String>::cast(name)); |
489 } | 488 } |
490 DCHECK(current.is_null() || | 489 DCHECK(current.is_null() || |
491 current->property_dictionary()->FindEntry(name) == | 490 current->property_dictionary()->FindEntry(name) == |
492 NameDictionary::kNotFound); | 491 NameDictionary::kNotFound); |
493 | 492 |
494 if (FLAG_eliminate_prototype_chain_checks && depth > 1) { | 493 if (depth > 1) { |
495 // TODO(jkummerow): Cache and re-use weak cell. | 494 // TODO(jkummerow): Cache and re-use weak cell. |
496 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); | 495 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
497 } | 496 } |
498 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 497 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
499 scratch2); | 498 scratch2); |
500 if (!FLAG_eliminate_prototype_chain_checks) { | |
501 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
502 __ lw(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
503 } | |
504 } else { | |
505 Register map_reg = scratch1; | |
506 if (!FLAG_eliminate_prototype_chain_checks) { | |
507 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
508 } | |
509 if (current_map->IsJSGlobalObjectMap()) { | |
510 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | |
511 name, scratch2, miss); | |
512 } else if (!FLAG_eliminate_prototype_chain_checks && | |
513 (depth != 1 || check == CHECK_ALL_MAPS)) { | |
514 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | |
515 __ GetWeakValue(scratch2, cell); | |
516 __ Branch(miss, ne, scratch2, Operand(map_reg)); | |
517 } | |
518 if (!FLAG_eliminate_prototype_chain_checks) { | |
519 __ lw(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | |
520 } | |
521 } | 499 } |
522 | 500 |
523 reg = holder_reg; // From now on the object will be in holder_reg. | 501 reg = holder_reg; // From now on the object will be in holder_reg. |
524 // Go to the next object in the prototype chain. | 502 // Go to the next object in the prototype chain. |
525 current = prototype; | 503 current = prototype; |
526 current_map = handle(current->map()); | 504 current_map = handle(current->map()); |
527 } | 505 } |
528 | 506 |
529 DCHECK(!current_map->IsJSGlobalProxyMap()); | 507 DCHECK(!current_map->IsJSGlobalProxyMap()); |
530 | 508 |
531 // Log the check depth. | 509 // Log the check depth. |
532 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 510 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
533 | 511 |
534 if (!FLAG_eliminate_prototype_chain_checks && | |
535 (depth != 0 || check == CHECK_ALL_MAPS)) { | |
536 // Check the holder map. | |
537 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
538 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | |
539 __ GetWeakValue(scratch2, cell); | |
540 __ Branch(miss, ne, scratch2, Operand(scratch1)); | |
541 } | |
542 | |
543 bool return_holder = return_what == RETURN_HOLDER; | 512 bool return_holder = return_what == RETURN_HOLDER; |
544 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { | 513 if (return_holder && depth != 0) { |
545 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); | 514 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
546 } | 515 } |
547 | 516 |
548 // Return the register containing the holder. | 517 // Return the register containing the holder. |
549 return return_holder ? reg : no_reg; | 518 return return_holder ? reg : no_reg; |
550 } | 519 } |
551 | 520 |
552 | 521 |
553 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 522 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
554 if (!miss->is_unused()) { | 523 if (!miss->is_unused()) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 // Return the generated code. | 689 // Return the generated code. |
721 return GetCode(kind(), name); | 690 return GetCode(kind(), name); |
722 } | 691 } |
723 | 692 |
724 | 693 |
725 #undef __ | 694 #undef __ |
726 } // namespace internal | 695 } // namespace internal |
727 } // namespace v8 | 696 } // namespace v8 |
728 | 697 |
729 #endif // V8_TARGET_ARCH_MIPS | 698 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |