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_PPC | 5 #if V8_TARGET_ARCH_PPC |
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 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 DCHECK(!value_reg.is(scratch)); | 395 DCHECK(!value_reg.is(scratch)); |
396 __ JumpIfSmi(value_reg, miss_label); | 396 __ JumpIfSmi(value_reg, miss_label); |
397 if (field_type->IsClass()) { | 397 if (field_type->IsClass()) { |
398 __ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 398 __ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
399 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), | 399 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), |
400 scratch); | 400 scratch); |
401 __ bne(miss_label); | 401 __ bne(miss_label); |
402 } | 402 } |
403 } | 403 } |
404 | 404 |
405 | |
406 Register PropertyHandlerCompiler::CheckPrototypes( | 405 Register PropertyHandlerCompiler::CheckPrototypes( |
407 Register object_reg, Register holder_reg, Register scratch1, | 406 Register object_reg, Register holder_reg, Register scratch1, |
408 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, | 407 Register scratch2, Handle<Name> name, Label* miss, |
409 ReturnHolder return_what) { | 408 ReturnHolder return_what) { |
410 Handle<Map> receiver_map = map(); | 409 Handle<Map> receiver_map = map(); |
411 | 410 |
412 // Make sure there's no overlap between holder and object registers. | 411 // Make sure there's no overlap between holder and object registers. |
413 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 412 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
414 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 413 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
415 !scratch2.is(scratch1)); | 414 !scratch2.is(scratch1)); |
416 | 415 |
417 Handle<Cell> validity_cell = | 416 Handle<Cell> validity_cell = |
418 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | 417 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
419 if (!validity_cell.is_null()) { | 418 if (!validity_cell.is_null()) { |
420 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); | 419 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); |
421 __ mov(scratch1, Operand(validity_cell)); | 420 __ mov(scratch1, Operand(validity_cell)); |
422 __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); | 421 __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
423 __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0); | 422 __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0); |
424 __ bne(miss); | 423 __ bne(miss); |
425 } | 424 } |
426 | 425 |
427 // The prototype chain of primitives (and their JSValue wrappers) depends | |
428 // on the native context, which can't be guarded by validity cells. | |
429 // |object_reg| holds the native context specific prototype in this case; | |
430 // we need to check its map. | |
431 if (check == CHECK_ALL_MAPS) { | |
432 __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | |
433 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | |
434 __ CmpWeakValue(scratch1, cell, scratch2); | |
435 __ b(ne, miss); | |
436 } | |
437 | |
438 // Keep track of the current object in register reg. | 426 // Keep track of the current object in register reg. |
439 Register reg = object_reg; | 427 Register reg = object_reg; |
440 int depth = 0; | 428 int depth = 0; |
441 | 429 |
442 Handle<JSObject> current = Handle<JSObject>::null(); | 430 Handle<JSObject> current = Handle<JSObject>::null(); |
443 if (receiver_map->IsJSGlobalObjectMap()) { | 431 if (receiver_map->IsJSGlobalObjectMap()) { |
444 current = isolate()->global_object(); | 432 current = isolate()->global_object(); |
445 } | 433 } |
446 | 434 |
447 Handle<JSObject> prototype = Handle<JSObject>::null(); | 435 Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()), |
448 Handle<Map> current_map = receiver_map; | 436 isolate()); |
449 Handle<Map> holder_map(holder()->map()); | 437 Handle<Map> holder_map(holder()->map()); |
450 // Traverse the prototype chain and check the maps in the prototype chain for | 438 // Traverse the prototype chain and check the maps in the prototype chain for |
451 // fast and global objects or do negative lookup for normal objects. | 439 // fast and global objects or do negative lookup for normal objects. |
452 while (!current_map.is_identical_to(holder_map)) { | 440 while (!current_map.is_identical_to(holder_map)) { |
453 ++depth; | 441 ++depth; |
454 | 442 |
455 // Only global objects and objects that do not require access | 443 // Only global objects and objects that do not require access |
456 // checks are allowed in stubs. | 444 // checks are allowed in stubs. |
457 DCHECK(current_map->IsJSGlobalProxyMap() || | 445 DCHECK(current_map->IsJSGlobalProxyMap() || |
458 !current_map->is_access_check_needed()); | 446 !current_map->is_access_check_needed()); |
459 | 447 |
460 prototype = handle(JSObject::cast(current_map->prototype())); | |
461 if (current_map->IsJSGlobalObjectMap()) { | 448 if (current_map->IsJSGlobalObjectMap()) { |
462 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 449 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
463 name, scratch2, miss); | 450 name, scratch2, miss); |
464 } else if (current_map->is_dictionary_map()) { | 451 } else if (current_map->is_dictionary_map()) { |
465 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 452 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
466 DCHECK(name->IsUniqueName()); | 453 DCHECK(name->IsUniqueName()); |
467 DCHECK(current.is_null() || | 454 DCHECK(current.is_null() || |
468 current->property_dictionary()->FindEntry(name) == | 455 current->property_dictionary()->FindEntry(name) == |
469 NameDictionary::kNotFound); | 456 NameDictionary::kNotFound); |
470 | 457 |
471 if (depth > 1) { | 458 if (depth > 1) { |
472 Handle<WeakCell> weak_cell = | 459 Handle<WeakCell> weak_cell = |
473 Map::GetOrCreatePrototypeWeakCell(current, isolate()); | 460 Map::GetOrCreatePrototypeWeakCell(current, isolate()); |
474 __ LoadWeakValue(reg, weak_cell, miss); | 461 __ LoadWeakValue(reg, weak_cell, miss); |
475 } | 462 } |
476 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 463 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
477 scratch2); | 464 scratch2); |
478 } | 465 } |
479 | 466 |
480 reg = holder_reg; // From now on the object will be in holder_reg. | 467 reg = holder_reg; // From now on the object will be in holder_reg. |
481 // Go to the next object in the prototype chain. | 468 // Go to the next object in the prototype chain. |
482 current = prototype; | 469 current = handle(JSObject::cast(current_map->prototype())); |
483 current_map = handle(current->map()); | 470 current_map = handle(current->map()); |
484 } | 471 } |
485 | 472 |
486 DCHECK(!current_map->IsJSGlobalProxyMap()); | 473 DCHECK(!current_map->IsJSGlobalProxyMap()); |
487 | 474 |
488 // Log the check depth. | 475 // Log the check depth. |
489 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 476 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
490 | 477 |
491 bool return_holder = return_what == RETURN_HOLDER; | 478 bool return_holder = return_what == RETURN_HOLDER; |
492 if (return_holder && depth != 0) { | 479 if (return_holder && depth != 0) { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 // Return the generated code. | 661 // Return the generated code. |
675 return GetCode(kind(), name); | 662 return GetCode(kind(), name); |
676 } | 663 } |
677 | 664 |
678 | 665 |
679 #undef __ | 666 #undef __ |
680 } // namespace internal | 667 } // namespace internal |
681 } // namespace v8 | 668 } // namespace v8 |
682 | 669 |
683 #endif // V8_TARGET_ARCH_ARM | 670 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |