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 #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/ic/call-optimization.h" | 9 #include "src/ic/call-optimization.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 } | 395 } |
396 __ Branch(&do_store, eq, map_reg, Operand(scratch)); | 396 __ Branch(&do_store, eq, map_reg, Operand(scratch)); |
397 } | 397 } |
398 __ bind(&do_store); | 398 __ bind(&do_store); |
399 } | 399 } |
400 } | 400 } |
401 | 401 |
402 | 402 |
403 Register PropertyHandlerCompiler::CheckPrototypes( | 403 Register PropertyHandlerCompiler::CheckPrototypes( |
404 Register object_reg, Register holder_reg, Register scratch1, | 404 Register object_reg, Register holder_reg, Register scratch1, |
405 Register scratch2, Handle<Name> name, Label* miss, | 405 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
406 PrototypeCheckType check) { | 406 ReturnHolder return_what) { |
407 Handle<Map> receiver_map = map(); | 407 Handle<Map> receiver_map = map(); |
408 | 408 |
409 // Make sure there's no overlap between holder and object registers. | 409 // Make sure there's no overlap between holder and object registers. |
410 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 410 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
411 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 411 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
412 !scratch2.is(scratch1)); | 412 !scratch2.is(scratch1)); |
413 | 413 |
| 414 if (FLAG_eliminate_prototype_chain_checks) { |
| 415 Handle<Cell> validity_cell = |
| 416 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| 417 if (!validity_cell.is_null()) { |
| 418 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), |
| 419 validity_cell->value()); |
| 420 __ li(scratch1, Operand(validity_cell)); |
| 421 __ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
| 422 __ Branch(miss, ne, scratch1, |
| 423 Operand(Smi::FromInt(Map::kPrototypeChainValid))); |
| 424 } |
| 425 |
| 426 // The prototype chain of primitives (and their JSValue wrappers) depends |
| 427 // on the native context, which can't be guarded by validity cells. |
| 428 // |object_reg| holds the native context specific prototype in this case; |
| 429 // we need to check its map. |
| 430 if (check == CHECK_ALL_MAPS) { |
| 431 __ ld(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 432 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 433 __ GetWeakValue(scratch2, cell); |
| 434 __ Branch(miss, ne, scratch1, Operand(scratch2)); |
| 435 } |
| 436 } |
| 437 |
414 // Keep track of the current object in register reg. | 438 // Keep track of the current object in register reg. |
415 Register reg = object_reg; | 439 Register reg = object_reg; |
416 int depth = 0; | 440 int depth = 0; |
417 | 441 |
418 Handle<JSObject> current = Handle<JSObject>::null(); | 442 Handle<JSObject> current = Handle<JSObject>::null(); |
419 if (receiver_map->IsJSGlobalObjectMap()) { | 443 if (receiver_map->IsJSGlobalObjectMap()) { |
420 current = isolate()->global_object(); | 444 current = isolate()->global_object(); |
421 } | 445 } |
422 | 446 |
423 // Check access rights to the global object. This has to happen after | 447 // Check access rights to the global object. This has to happen after |
(...skipping 24 matching lines...) Expand all Loading... |
448 !current_map->IsJSGlobalObjectMap()) { | 472 !current_map->IsJSGlobalObjectMap()) { |
449 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 473 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
450 if (!name->IsUniqueName()) { | 474 if (!name->IsUniqueName()) { |
451 DCHECK(name->IsString()); | 475 DCHECK(name->IsString()); |
452 name = factory()->InternalizeString(Handle<String>::cast(name)); | 476 name = factory()->InternalizeString(Handle<String>::cast(name)); |
453 } | 477 } |
454 DCHECK(current.is_null() || | 478 DCHECK(current.is_null() || |
455 current->property_dictionary()->FindEntry(name) == | 479 current->property_dictionary()->FindEntry(name) == |
456 NameDictionary::kNotFound); | 480 NameDictionary::kNotFound); |
457 | 481 |
| 482 if (FLAG_eliminate_prototype_chain_checks && depth > 1) { |
| 483 // TODO(jkummerow): Cache and re-use weak cell. |
| 484 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 485 } |
458 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 486 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
459 scratch2); | 487 scratch2); |
460 | 488 if (!FLAG_eliminate_prototype_chain_checks) { |
461 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 489 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
462 reg = holder_reg; // From now on the object will be in holder_reg. | 490 __ ld(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
463 __ ld(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 491 } |
464 } else { | 492 } else { |
465 Register map_reg = scratch1; | 493 Register map_reg = scratch1; |
466 __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 494 if (!FLAG_eliminate_prototype_chain_checks) { |
467 | 495 __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 496 } |
468 if (current_map->IsJSGlobalObjectMap()) { | 497 if (current_map->IsJSGlobalObjectMap()) { |
469 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 498 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
470 name, scratch2, miss); | 499 name, scratch2, miss); |
471 } else if (depth != 1 || check == CHECK_ALL_MAPS) { | 500 } else if (!FLAG_eliminate_prototype_chain_checks && |
| 501 (depth != 1 || check == CHECK_ALL_MAPS)) { |
472 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 502 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
473 __ GetWeakValue(scratch2, cell); | 503 __ GetWeakValue(scratch2, cell); |
474 __ Branch(miss, ne, scratch2, Operand(map_reg)); | 504 __ Branch(miss, ne, scratch2, Operand(map_reg)); |
475 } | 505 } |
476 | 506 if (!FLAG_eliminate_prototype_chain_checks) { |
477 reg = holder_reg; // From now on the object will be in holder_reg. | 507 __ ld(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
478 | 508 } |
479 __ ld(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | |
480 } | 509 } |
481 | 510 |
| 511 reg = holder_reg; // From now on the object will be in holder_reg. |
482 // Go to the next object in the prototype chain. | 512 // Go to the next object in the prototype chain. |
483 current = prototype; | 513 current = prototype; |
484 current_map = handle(current->map()); | 514 current_map = handle(current->map()); |
485 } | 515 } |
486 | 516 |
487 DCHECK(!current_map->IsJSGlobalProxyMap()); | 517 DCHECK(!current_map->IsJSGlobalProxyMap()); |
488 | 518 |
489 // Log the check depth. | 519 // Log the check depth. |
490 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 520 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
491 | 521 |
492 if (depth != 0 || check == CHECK_ALL_MAPS) { | 522 if (!FLAG_eliminate_prototype_chain_checks && |
| 523 (depth != 0 || check == CHECK_ALL_MAPS)) { |
493 // Check the holder map. | 524 // Check the holder map. |
494 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 525 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
495 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 526 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
496 __ GetWeakValue(scratch2, cell); | 527 __ GetWeakValue(scratch2, cell); |
497 __ Branch(miss, ne, scratch2, Operand(scratch1)); | 528 __ Branch(miss, ne, scratch2, Operand(scratch1)); |
498 } | 529 } |
499 | 530 |
| 531 bool return_holder = return_what == RETURN_HOLDER; |
| 532 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { |
| 533 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 534 } |
| 535 |
500 // Return the register containing the holder. | 536 // Return the register containing the holder. |
501 return reg; | 537 return return_holder ? reg : no_reg; |
502 } | 538 } |
503 | 539 |
504 | 540 |
505 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 541 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
506 if (!miss->is_unused()) { | 542 if (!miss->is_unused()) { |
507 Label success; | 543 Label success; |
508 __ Branch(&success); | 544 __ Branch(&success); |
509 __ bind(miss); | 545 __ bind(miss); |
510 if (IC::ICUseVector(kind())) { | 546 if (IC::ICUseVector(kind())) { |
511 DCHECK(kind() == Code::LOAD_IC); | 547 DCHECK(kind() == Code::LOAD_IC); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 } | 742 } |
707 | 743 |
708 | 744 |
709 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 745 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
710 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 746 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
711 Label miss; | 747 Label miss; |
712 if (IC::ICUseVector(kind())) { | 748 if (IC::ICUseVector(kind())) { |
713 PushVectorAndSlot(); | 749 PushVectorAndSlot(); |
714 } | 750 } |
715 | 751 |
716 FrontendHeader(receiver(), name, &miss); | 752 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
717 | 753 |
718 // Get the value from the cell. | 754 // Get the value from the cell. |
719 Register result = StoreDescriptor::ValueRegister(); | 755 Register result = StoreDescriptor::ValueRegister(); |
720 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); | 756 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); |
721 __ LoadWeakValue(result, weak_cell, &miss); | 757 __ LoadWeakValue(result, weak_cell, &miss); |
722 __ ld(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 758 __ ld(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
723 | 759 |
724 // Check for deleted property if property can actually be deleted. | 760 // Check for deleted property if property can actually be deleted. |
725 if (is_configurable) { | 761 if (is_configurable) { |
726 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 762 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
(...skipping 13 matching lines...) Expand all Loading... |
740 // Return the generated code. | 776 // Return the generated code. |
741 return GetCode(kind(), Code::NORMAL, name); | 777 return GetCode(kind(), Code::NORMAL, name); |
742 } | 778 } |
743 | 779 |
744 | 780 |
745 #undef __ | 781 #undef __ |
746 } | 782 } |
747 } // namespace v8::internal | 783 } // namespace v8::internal |
748 | 784 |
749 #endif // V8_TARGET_ARCH_MIPS64 | 785 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |