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