Chromium Code Reviews

Side by Side Diff: src/objects.cc

Issue 12319144: Avoid TLS accesses in Object::Lookup and Object::GetPrototype. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Simplified Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/property.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 117 matching lines...)
128 } 128 }
129 return heap_object->GetHeap()->true_value(); 129 return heap_object->GetHeap()->true_value();
130 } 130 }
131 131
132 132
133 void Object::Lookup(String* name, LookupResult* result) { 133 void Object::Lookup(String* name, LookupResult* result) {
134 Object* holder = NULL; 134 Object* holder = NULL;
135 if (IsJSReceiver()) { 135 if (IsJSReceiver()) {
136 holder = this; 136 holder = this;
137 } else { 137 } else {
138 Context* native_context = Isolate::Current()->context()->native_context(); 138 Context* native_context = result->isolate()->context()->native_context();
139 if (IsNumber()) { 139 if (IsNumber()) {
140 holder = native_context->number_function()->instance_prototype(); 140 holder = native_context->number_function()->instance_prototype();
141 } else if (IsString()) { 141 } else if (IsString()) {
142 holder = native_context->string_function()->instance_prototype(); 142 holder = native_context->string_function()->instance_prototype();
143 } else if (IsBoolean()) { 143 } else if (IsBoolean()) {
144 holder = native_context->boolean_function()->instance_prototype(); 144 holder = native_context->boolean_function()->instance_prototype();
145 } else { 145 } else {
146 Isolate::Current()->PushStackTraceAndDie( 146 Isolate::Current()->PushStackTraceAndDie(
147 0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001); 147 0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
148 } 148 }
(...skipping 457 matching lines...)
606 } 606 }
607 607
608 608
609 MaybeObject* Object::GetProperty(Object* receiver, 609 MaybeObject* Object::GetProperty(Object* receiver,
610 LookupResult* result, 610 LookupResult* result,
611 String* name, 611 String* name,
612 PropertyAttributes* attributes) { 612 PropertyAttributes* attributes) {
613 // Make sure that the top context does not change when doing 613 // Make sure that the top context does not change when doing
614 // callbacks or interceptor calls. 614 // callbacks or interceptor calls.
615 AssertNoContextChange ncc; 615 AssertNoContextChange ncc;
616 Heap* heap = name->GetHeap(); 616 Isolate* isolate = name->GetIsolate();
617 Heap* heap = isolate->heap();
617 618
618 // Traverse the prototype chain from the current object (this) to 619 // Traverse the prototype chain from the current object (this) to
619 // the holder and check for access rights. This avoids traversing the 620 // the holder and check for access rights. This avoids traversing the
620 // objects more than once in case of interceptors, because the 621 // objects more than once in case of interceptors, because the
621 // holder will always be the interceptor holder and the search may 622 // holder will always be the interceptor holder and the search may
622 // only continue with a current object just after the interceptor 623 // only continue with a current object just after the interceptor
623 // holder in the prototype chain. 624 // holder in the prototype chain.
624 // Proxy handlers do not use the proxy's prototype, so we can skip this. 625 // Proxy handlers do not use the proxy's prototype, so we can skip this.
625 if (!result->IsHandler()) { 626 if (!result->IsHandler()) {
626 Object* last = result->IsProperty() 627 Object* last = result->IsProperty()
627 ? result->holder() 628 ? result->holder()
628 : Object::cast(heap->null_value()); 629 : Object::cast(heap->null_value());
629 ASSERT(this != this->GetPrototype()); 630 ASSERT(this != this->GetPrototype(isolate));
630 for (Object* current = this; true; current = current->GetPrototype()) { 631 for (Object* current = this;
632 true;
633 current = current->GetPrototype(isolate)) {
631 if (current->IsAccessCheckNeeded()) { 634 if (current->IsAccessCheckNeeded()) {
632 // Check if we're allowed to read from the current object. Note 635 // Check if we're allowed to read from the current object. Note
633 // that even though we may not actually end up loading the named 636 // that even though we may not actually end up loading the named
634 // property from the current object, we still check that we have 637 // property from the current object, we still check that we have
635 // access to it. 638 // access to it.
636 // TODO(dcarney): revert. 639 // TODO(dcarney): revert.
637 CHECK(current->IsJSObject()); 640 CHECK(current->IsJSObject());
638 JSObject* checked = JSObject::cast(current); 641 JSObject* checked = JSObject::cast(current);
639 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) { 642 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
640 return checked->GetPropertyWithFailedAccessCheck(receiver, 643 return checked->GetPropertyWithFailedAccessCheck(receiver,
(...skipping 39 matching lines...)
680 case NONEXISTENT: 683 case NONEXISTENT:
681 UNREACHABLE(); 684 UNREACHABLE();
682 break; 685 break;
683 } 686 }
684 UNREACHABLE(); 687 UNREACHABLE();
685 return NULL; 688 return NULL;
686 } 689 }
687 690
688 691
689 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { 692 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
690 Heap* heap = IsSmi() 693 Isolate* isolate = IsSmi()
691 ? Isolate::Current()->heap() 694 ? Isolate::Current()
692 : HeapObject::cast(this)->GetHeap(); 695 : HeapObject::cast(this)->GetIsolate();
696 Heap* heap = isolate->heap();
693 Object* holder = this; 697 Object* holder = this;
694 698
695 // Iterate up the prototype chain until an element is found or the null 699 // Iterate up the prototype chain until an element is found or the null
696 // prototype is encountered. 700 // prototype is encountered.
697 for (holder = this; 701 for (holder = this;
698 holder != heap->null_value(); 702 holder != heap->null_value();
699 holder = holder->GetPrototype()) { 703 holder = holder->GetPrototype(isolate)) {
700 if (!holder->IsJSObject()) { 704 if (!holder->IsJSObject()) {
701 Isolate* isolate = heap->isolate();
702 Context* native_context = isolate->context()->native_context(); 705 Context* native_context = isolate->context()->native_context();
703 if (holder->IsNumber()) { 706 if (holder->IsNumber()) {
704 holder = native_context->number_function()->instance_prototype(); 707 holder = native_context->number_function()->instance_prototype();
705 } else if (holder->IsString()) { 708 } else if (holder->IsString()) {
706 holder = native_context->string_function()->instance_prototype(); 709 holder = native_context->string_function()->instance_prototype();
707 } else if (holder->IsBoolean()) { 710 } else if (holder->IsBoolean()) {
708 holder = native_context->boolean_function()->instance_prototype(); 711 holder = native_context->boolean_function()->instance_prototype();
709 } else if (holder->IsJSProxy()) { 712 } else if (holder->IsJSProxy()) {
710 return JSProxy::cast(holder)->GetElementWithHandler(receiver, index); 713 return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
711 } else { 714 } else {
(...skipping 25 matching lines...)
737 MaybeObject* result = js_object->GetElementsAccessor()->Get( 740 MaybeObject* result = js_object->GetElementsAccessor()->Get(
738 receiver, js_object, index); 741 receiver, js_object, index);
739 if (result != heap->the_hole_value()) return result; 742 if (result != heap->the_hole_value()) return result;
740 } 743 }
741 } 744 }
742 745
743 return heap->undefined_value(); 746 return heap->undefined_value();
744 } 747 }
745 748
746 749
747 Object* Object::GetPrototype() { 750 Object* Object::GetPrototype(Isolate* isolate) {
748 if (IsSmi()) { 751 if (IsSmi()) {
749 Heap* heap = Isolate::Current()->heap(); 752 Heap* heap = Isolate::Current()->heap();
ulan 2013/02/27 13:19:14 Shouldn't this be isolate->heap()?
750 Context* context = heap->isolate()->context()->native_context(); 753 Context* context = heap->isolate()->context()->native_context();
751 return context->number_function()->instance_prototype(); 754 return context->number_function()->instance_prototype();
752 } 755 }
753 756
754 HeapObject* heap_object = HeapObject::cast(this); 757 HeapObject* heap_object = HeapObject::cast(this);
755 758
756 // The object is either a number, a string, a boolean, 759 // The object is either a number, a string, a boolean,
757 // a real JS object, or a Harmony proxy. 760 // a real JS object, or a Harmony proxy.
758 if (heap_object->IsJSReceiver()) { 761 if (heap_object->IsJSReceiver()) {
759 return heap_object->map()->prototype(); 762 return heap_object->map()->prototype();
(...skipping 1333 matching lines...)
2093 2096
2094 2097
2095 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( 2098 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
2096 uint32_t index, 2099 uint32_t index,
2097 Object* value, 2100 Object* value,
2098 bool* found, 2101 bool* found,
2099 StrictModeFlag strict_mode) { 2102 StrictModeFlag strict_mode) {
2100 Heap* heap = GetHeap(); 2103 Heap* heap = GetHeap();
2101 for (Object* pt = GetPrototype(); 2104 for (Object* pt = GetPrototype();
2102 pt != heap->null_value(); 2105 pt != heap->null_value();
2103 pt = pt->GetPrototype()) { 2106 pt = pt->GetPrototype(GetIsolate())) {
2104 if (pt->IsJSProxy()) { 2107 if (pt->IsJSProxy()) {
2105 String* name; 2108 String* name;
2106 MaybeObject* maybe = GetHeap()->Uint32ToString(index); 2109 MaybeObject* maybe = heap->Uint32ToString(index);
2107 if (!maybe->To<String>(&name)) { 2110 if (!maybe->To<String>(&name)) {
2108 *found = true; // Force abort 2111 *found = true; // Force abort
2109 return maybe; 2112 return maybe;
2110 } 2113 }
2111 return JSProxy::cast(pt)->SetPropertyViaPrototypesWithHandler( 2114 return JSProxy::cast(pt)->SetPropertyViaPrototypesWithHandler(
2112 this, name, value, NONE, strict_mode, found); 2115 this, name, value, NONE, strict_mode, found);
2113 } 2116 }
2114 if (!JSObject::cast(pt)->HasDictionaryElements()) { 2117 if (!JSObject::cast(pt)->HasDictionaryElements()) {
2115 continue; 2118 continue;
2116 } 2119 }
(...skipping 379 matching lines...)
2496 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { 2499 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
2497 LocalLookupRealNamedProperty(name, result); 2500 LocalLookupRealNamedProperty(name, result);
2498 if (result->IsFound()) return; 2501 if (result->IsFound()) return;
2499 2502
2500 LookupRealNamedPropertyInPrototypes(name, result); 2503 LookupRealNamedPropertyInPrototypes(name, result);
2501 } 2504 }
2502 2505
2503 2506
2504 void JSObject::LookupRealNamedPropertyInPrototypes(String* name, 2507 void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
2505 LookupResult* result) { 2508 LookupResult* result) {
2506 Heap* heap = GetHeap(); 2509 Isolate* isolate = GetIsolate();
2510 Heap* heap = isolate->heap();
2507 for (Object* pt = GetPrototype(); 2511 for (Object* pt = GetPrototype();
2508 pt != heap->null_value(); 2512 pt != heap->null_value();
2509 pt = pt->GetPrototype()) { 2513 pt = pt->GetPrototype(isolate)) {
2510 if (pt->IsJSProxy()) { 2514 if (pt->IsJSProxy()) {
2511 return result->HandlerResult(JSProxy::cast(pt)); 2515 return result->HandlerResult(JSProxy::cast(pt));
2512 } 2516 }
2513 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); 2517 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
2514 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR)); 2518 ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
2515 if (result->IsFound()) return; 2519 if (result->IsFound()) return;
2516 } 2520 }
2517 result->NotFound(); 2521 result->NotFound();
2518 } 2522 }
2519 2523
(...skipping 5622 matching lines...)
8142 8146
8143 8147
8144 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { 8148 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
8145 // Check the basic conditions for generating inline constructor code. 8149 // Check the basic conditions for generating inline constructor code.
8146 if (!FLAG_inline_new 8150 if (!FLAG_inline_new
8147 || !has_only_simple_this_property_assignments() 8151 || !has_only_simple_this_property_assignments()
8148 || this_property_assignments_count() == 0) { 8152 || this_property_assignments_count() == 0) {
8149 return false; 8153 return false;
8150 } 8154 }
8151 8155
8152 Heap* heap = GetHeap(); 8156 Isolate* isolate = GetIsolate();
8157 Heap* heap = isolate->heap();
8153 8158
8154 // Traverse the proposed prototype chain looking for properties of the 8159 // Traverse the proposed prototype chain looking for properties of the
8155 // same names as are set by the inline constructor. 8160 // same names as are set by the inline constructor.
8156 for (Object* obj = prototype; 8161 for (Object* obj = prototype;
8157 obj != heap->null_value(); 8162 obj != heap->null_value();
8158 obj = obj->GetPrototype()) { 8163 obj = obj->GetPrototype(isolate)) {
8159 JSReceiver* receiver = JSReceiver::cast(obj); 8164 JSReceiver* receiver = JSReceiver::cast(obj);
8160 for (int i = 0; i < this_property_assignments_count(); i++) { 8165 for (int i = 0; i < this_property_assignments_count(); i++) {
8161 LookupResult result(heap->isolate()); 8166 LookupResult result(heap->isolate());
8162 String* name = GetThisPropertyAssignmentName(i); 8167 String* name = GetThisPropertyAssignmentName(i);
8163 receiver->LocalLookup(name, &result); 8168 receiver->LocalLookup(name, &result);
8164 if (result.IsFound()) { 8169 if (result.IsFound()) {
8165 switch (result.type()) { 8170 switch (result.type()) {
8166 case NORMAL: 8171 case NORMAL:
8167 case FIELD: 8172 case FIELD:
8168 case CONSTANT_FUNCTION: 8173 case CONSTANT_FUNCTION:
(...skipping 1435 matching lines...)
9604 Deoptimizer::DeoptimizeAllFunctionsWith(&filter); 9609 Deoptimizer::DeoptimizeAllFunctionsWith(&filter);
9605 } 9610 }
9606 9611
9607 9612
9608 MaybeObject* JSReceiver::SetPrototype(Object* value, 9613 MaybeObject* JSReceiver::SetPrototype(Object* value,
9609 bool skip_hidden_prototypes) { 9614 bool skip_hidden_prototypes) {
9610 #ifdef DEBUG 9615 #ifdef DEBUG
9611 int size = Size(); 9616 int size = Size();
9612 #endif 9617 #endif
9613 9618
9614 Heap* heap = GetHeap(); 9619 Isolate* isolate = GetIsolate();
9620 Heap* heap = isolate->heap();
9615 // Silently ignore the change if value is not a JSObject or null. 9621 // Silently ignore the change if value is not a JSObject or null.
9616 // SpiderMonkey behaves this way. 9622 // SpiderMonkey behaves this way.
9617 if (!value->IsJSReceiver() && !value->IsNull()) return value; 9623 if (!value->IsJSReceiver() && !value->IsNull()) return value;
9618 9624
9619 // From 8.6.2 Object Internal Methods 9625 // From 8.6.2 Object Internal Methods
9620 // ... 9626 // ...
9621 // In addition, if [[Extensible]] is false the value of the [[Class]] and 9627 // In addition, if [[Extensible]] is false the value of the [[Class]] and
9622 // [[Prototype]] internal properties of the object may not be modified. 9628 // [[Prototype]] internal properties of the object may not be modified.
9623 // ... 9629 // ...
9624 // Implementation specific extensions that modify [[Class]], [[Prototype]] 9630 // Implementation specific extensions that modify [[Class]], [[Prototype]]
9625 // or [[Extensible]] must not violate the invariants defined in the preceding 9631 // or [[Extensible]] must not violate the invariants defined in the preceding
9626 // paragraph. 9632 // paragraph.
9627 if (!this->map()->is_extensible()) { 9633 if (!this->map()->is_extensible()) {
9628 HandleScope scope(heap->isolate()); 9634 HandleScope scope(isolate);
9629 Handle<Object> handle(this, heap->isolate()); 9635 Handle<Object> handle(this, isolate);
9630 return heap->isolate()->Throw( 9636 return isolate->Throw(
9631 *FACTORY->NewTypeError("non_extensible_proto", 9637 *isolate->factory()->NewTypeError("non_extensible_proto",
9632 HandleVector<Object>(&handle, 1))); 9638 HandleVector<Object>(&handle, 1)));
9633 } 9639 }
9634 9640
9635 // Before we can set the prototype we need to be sure 9641 // Before we can set the prototype we need to be sure
9636 // prototype cycles are prevented. 9642 // prototype cycles are prevented.
9637 // It is sufficient to validate that the receiver is not in the new prototype 9643 // It is sufficient to validate that the receiver is not in the new prototype
9638 // chain. 9644 // chain.
9639 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { 9645 for (Object* pt = value;
9646 pt != heap->null_value();
9647 pt = pt->GetPrototype(isolate)) {
9640 if (JSReceiver::cast(pt) == this) { 9648 if (JSReceiver::cast(pt) == this) {
9641 // Cycle detected. 9649 // Cycle detected.
9642 HandleScope scope(heap->isolate()); 9650 HandleScope scope(isolate);
9643 return heap->isolate()->Throw( 9651 return isolate->Throw(
9644 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); 9652 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
9645 } 9653 }
9646 } 9654 }
9647 9655
9648 JSReceiver* real_receiver = this; 9656 JSReceiver* real_receiver = this;
9649 9657
9650 if (skip_hidden_prototypes) { 9658 if (skip_hidden_prototypes) {
9651 // Find the first object in the chain whose prototype object is not 9659 // Find the first object in the chain whose prototype object is not
9652 // hidden and set the new prototype on that object. 9660 // hidden and set the new prototype on that object.
9653 Object* current_proto = real_receiver->GetPrototype(); 9661 Object* current_proto = real_receiver->GetPrototype();
9654 while (current_proto->IsJSObject() && 9662 while (current_proto->IsJSObject() &&
9655 JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) { 9663 JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
9656 real_receiver = JSReceiver::cast(current_proto); 9664 real_receiver = JSReceiver::cast(current_proto);
9657 current_proto = current_proto->GetPrototype(); 9665 current_proto = current_proto->GetPrototype(isolate);
9658 } 9666 }
9659 } 9667 }
9660 9668
9661 // Set the new prototype of the object. 9669 // Set the new prototype of the object.
9662 Map* map = real_receiver->map(); 9670 Map* map = real_receiver->map();
9663 9671
9664 // Nothing to do if prototype is already set. 9672 // Nothing to do if prototype is already set.
9665 if (map->prototype() == value) return value; 9673 if (map->prototype() == value) return value;
9666 9674
9667 if (value->IsJSObject()) { 9675 if (value->IsJSObject()) {
(...skipping 4313 matching lines...)
13981 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13989 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13982 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13990 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13983 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13991 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13984 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13992 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13985 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13993 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13986 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13994 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13987 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13995 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13988 } 13996 }
13989 13997
13990 } } // namespace v8::internal 13998 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/property.h » ('j') | no next file with comments »

Powered by Google App Engine