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_X64 | 5 #if V8_TARGET_ARCH_X64 |
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 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 __ JumpIfSmi(value_reg, miss_label); | 394 __ JumpIfSmi(value_reg, miss_label); |
395 if (field_type->IsClass()) { | 395 if (field_type->IsClass()) { |
396 Label do_store; | 396 Label do_store; |
397 __ movp(map_reg, FieldOperand(value_reg, HeapObject::kMapOffset)); | 397 __ movp(map_reg, FieldOperand(value_reg, HeapObject::kMapOffset)); |
398 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), | 398 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), |
399 scratch); | 399 scratch); |
400 __ j(not_equal, miss_label); | 400 __ j(not_equal, miss_label); |
401 } | 401 } |
402 } | 402 } |
403 | 403 |
404 | |
405 Register PropertyHandlerCompiler::CheckPrototypes( | 404 Register PropertyHandlerCompiler::CheckPrototypes( |
406 Register object_reg, Register holder_reg, Register scratch1, | 405 Register object_reg, Register holder_reg, Register scratch1, |
407 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, | 406 Register scratch2, Handle<Name> name, Label* miss, |
408 ReturnHolder return_what) { | 407 ReturnHolder return_what) { |
409 Handle<Map> receiver_map = map(); | 408 Handle<Map> receiver_map = map(); |
410 | 409 |
411 // Make sure there's no overlap between holder and object registers. | 410 // Make sure there's no overlap between holder and object registers. |
412 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 411 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
413 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 412 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
414 !scratch2.is(scratch1)); | 413 !scratch2.is(scratch1)); |
415 | 414 |
416 Handle<Cell> validity_cell = | 415 Handle<Cell> validity_cell = |
417 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | 416 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
418 if (!validity_cell.is_null()) { | 417 if (!validity_cell.is_null()) { |
419 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); | 418 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); |
420 __ Move(scratch1, validity_cell, RelocInfo::CELL); | 419 __ Move(scratch1, validity_cell, RelocInfo::CELL); |
421 // Move(..., CELL) loads the payload's address! | 420 // Move(..., CELL) loads the payload's address! |
422 __ SmiCompare(Operand(scratch1, 0), | 421 __ SmiCompare(Operand(scratch1, 0), |
423 Smi::FromInt(Map::kPrototypeChainValid)); | 422 Smi::FromInt(Map::kPrototypeChainValid)); |
424 __ j(not_equal, miss); | 423 __ j(not_equal, 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 __ movp(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset)); | |
433 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | |
434 __ CmpWeakValue(scratch1, cell, scratch2); | |
435 __ j(not_equal, miss); | |
436 } | |
437 | |
438 // Keep track of the current object in register reg. On the first | 426 // Keep track of the current object in register reg. On the first |
439 // iteration, reg is an alias for object_reg, on later iterations, | 427 // iteration, reg is an alias for object_reg, on later iterations, |
440 // it is an alias for holder_reg. | 428 // it is an alias for holder_reg. |
441 Register reg = object_reg; | 429 Register reg = object_reg; |
442 int depth = 0; | 430 int depth = 0; |
443 | 431 |
444 Handle<JSObject> current = Handle<JSObject>::null(); | 432 Handle<JSObject> current = Handle<JSObject>::null(); |
445 if (receiver_map->IsJSGlobalObjectMap()) { | 433 if (receiver_map->IsJSGlobalObjectMap()) { |
446 current = isolate()->global_object(); | 434 current = isolate()->global_object(); |
447 } | 435 } |
448 | 436 |
449 Handle<JSObject> prototype = Handle<JSObject>::null(); | 437 Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()), |
450 Handle<Map> current_map = receiver_map; | 438 isolate()); |
451 Handle<Map> holder_map(holder()->map()); | 439 Handle<Map> holder_map(holder()->map()); |
452 // Traverse the prototype chain and check the maps in the prototype chain for | 440 // Traverse the prototype chain and check the maps in the prototype chain for |
453 // fast and global objects or do negative lookup for normal objects. | 441 // fast and global objects or do negative lookup for normal objects. |
454 while (!current_map.is_identical_to(holder_map)) { | 442 while (!current_map.is_identical_to(holder_map)) { |
455 ++depth; | 443 ++depth; |
456 | 444 |
457 prototype = handle(JSObject::cast(current_map->prototype())); | |
458 if (current_map->IsJSGlobalObjectMap()) { | 445 if (current_map->IsJSGlobalObjectMap()) { |
459 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 446 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
460 name, scratch2, miss); | 447 name, scratch2, miss); |
461 } else if (current_map->is_dictionary_map()) { | 448 } else if (current_map->is_dictionary_map()) { |
462 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 449 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
463 DCHECK(name->IsUniqueName()); | 450 DCHECK(name->IsUniqueName()); |
464 DCHECK(current.is_null() || | 451 DCHECK(current.is_null() || |
465 current->property_dictionary()->FindEntry(name) == | 452 current->property_dictionary()->FindEntry(name) == |
466 NameDictionary::kNotFound); | 453 NameDictionary::kNotFound); |
467 | 454 |
468 if (depth > 1) { | 455 if (depth > 1) { |
469 Handle<WeakCell> weak_cell = | 456 Handle<WeakCell> weak_cell = |
470 Map::GetOrCreatePrototypeWeakCell(current, isolate()); | 457 Map::GetOrCreatePrototypeWeakCell(current, isolate()); |
471 __ LoadWeakValue(reg, weak_cell, miss); | 458 __ LoadWeakValue(reg, weak_cell, miss); |
472 } | 459 } |
473 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 460 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
474 scratch2); | 461 scratch2); |
475 } | 462 } |
476 | 463 |
477 reg = holder_reg; // From now on the object will be in holder_reg. | 464 reg = holder_reg; // From now on the object will be in holder_reg. |
478 // Go to the next object in the prototype chain. | 465 // Go to the next object in the prototype chain. |
479 current = prototype; | 466 current = handle(JSObject::cast(current_map->prototype())); |
480 current_map = handle(current->map()); | 467 current_map = handle(current->map()); |
481 } | 468 } |
482 | 469 |
483 DCHECK(!current_map->IsJSGlobalProxyMap()); | 470 DCHECK(!current_map->IsJSGlobalProxyMap()); |
484 | 471 |
485 // Log the check depth. | 472 // Log the check depth. |
486 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 473 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
487 | 474 |
488 bool return_holder = return_what == RETURN_HOLDER; | 475 bool return_holder = return_what == RETURN_HOLDER; |
489 if (return_holder && depth != 0) { | 476 if (return_holder && depth != 0) { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 // Return the generated code. | 664 // Return the generated code. |
678 return GetCode(kind(), name); | 665 return GetCode(kind(), name); |
679 } | 666 } |
680 | 667 |
681 | 668 |
682 #undef __ | 669 #undef __ |
683 } // namespace internal | 670 } // namespace internal |
684 } // namespace v8 | 671 } // namespace v8 |
685 | 672 |
686 #endif // V8_TARGET_ARCH_X64 | 673 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |