Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: src/objects.cc

Issue 9152001: Introduce a new AccessorPair type for handling JavaScript accessors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Incorporated review comments Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 result = call_fun(v8::Utils::ToLocal(key), info); 239 result = call_fun(v8::Utils::ToLocal(key), info);
240 } 240 }
241 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 241 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
242 if (result.IsEmpty()) { 242 if (result.IsEmpty()) {
243 return isolate->heap()->undefined_value(); 243 return isolate->heap()->undefined_value();
244 } 244 }
245 return *v8::Utils::OpenHandle(*result); 245 return *v8::Utils::OpenHandle(*result);
246 } 246 }
247 247
248 // __defineGetter__ callback 248 // __defineGetter__ callback
249 if (structure->IsFixedArray()) { 249 if (structure->IsAccessorPair()) {
250 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); 250 Object* getter = AccessorPair::cast(structure)->getter();
251 if (getter->IsSpecFunction()) { 251 if (getter->IsSpecFunction()) {
252 // TODO(rossberg): nicer would be to cast to some JSCallable here... 252 // TODO(rossberg): nicer would be to cast to some JSCallable here...
253 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); 253 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
254 } 254 }
255 // Getter is not a function. 255 // Getter is not a function.
256 return isolate->heap()->undefined_value(); 256 return isolate->heap()->undefined_value();
257 } 257 }
258 258
259 UNREACHABLE(); 259 UNREACHABLE();
260 return NULL; 260 return NULL;
(...skipping 1771 matching lines...) Expand 10 before | Expand all | Expand 10 after
2032 // Leaving JavaScript. 2032 // Leaving JavaScript.
2033 VMState state(isolate, EXTERNAL); 2033 VMState state(isolate, EXTERNAL);
2034 call_fun(v8::Utils::ToLocal(key), 2034 call_fun(v8::Utils::ToLocal(key),
2035 v8::Utils::ToLocal(value_handle), 2035 v8::Utils::ToLocal(value_handle),
2036 info); 2036 info);
2037 } 2037 }
2038 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 2038 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
2039 return *value_handle; 2039 return *value_handle;
2040 } 2040 }
2041 2041
2042 if (structure->IsFixedArray()) { 2042 if (structure->IsAccessorPair()) {
2043 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); 2043 Object* setter = AccessorPair::cast(structure)->setter();
2044 if (setter->IsSpecFunction()) { 2044 if (setter->IsSpecFunction()) {
2045 // TODO(rossberg): nicer would be to cast to some JSCallable here... 2045 // TODO(rossberg): nicer would be to cast to some JSCallable here...
2046 return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value); 2046 return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
2047 } else { 2047 } else {
2048 if (strict_mode == kNonStrictMode) { 2048 if (strict_mode == kNonStrictMode) {
2049 return value; 2049 return value;
2050 } 2050 }
2051 Handle<String> key(name); 2051 Handle<String> key(name);
2052 Handle<Object> holder_handle(holder, isolate); 2052 Handle<Object> holder_handle(holder, isolate);
2053 Handle<Object> args[2] = { key, holder_handle }; 2053 Handle<Object> args[2] = { key, holder_handle };
(...skipping 2292 matching lines...) Expand 10 before | Expand all | Expand 10 after
4346 current != heap->null_value() && current->IsJSObject(); 4346 current != heap->null_value() && current->IsJSObject();
4347 current = JSObject::cast(current)->GetPrototype()) { 4347 current = JSObject::cast(current)->GetPrototype()) {
4348 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); 4348 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4349 if (result->IsProperty() && result->type() == CALLBACKS) return; 4349 if (result->IsProperty() && result->type() == CALLBACKS) return;
4350 } 4350 }
4351 result->NotFound(); 4351 result->NotFound();
4352 } 4352 }
4353 4353
4354 4354
4355 // Search for a getter or setter in an elements dictionary and update its 4355 // Search for a getter or setter in an elements dictionary and update its
4356 // attributes. Returns either undefined if the element is non-deletable, or 4356 // attributes. Returns either undefined if the element is non-deletable, or the
4357 // the getter/setter pair (fixed array) if there is an existing one, or the 4357 // getter/setter pair if there is an existing one, or the hole value if the
4358 // hole value if the element does not exist or is a normal non-getter/setter 4358 // element does not exist or is a normal non-getter/setter data element.
4359 // data element.
4360 static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary, 4359 static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary,
4361 uint32_t index, 4360 uint32_t index,
4362 PropertyAttributes attributes, 4361 PropertyAttributes attributes,
4363 Heap* heap) { 4362 Heap* heap) {
4364 int entry = dictionary->FindEntry(index); 4363 int entry = dictionary->FindEntry(index);
4365 if (entry != NumberDictionary::kNotFound) { 4364 if (entry != NumberDictionary::kNotFound) {
4366 Object* result = dictionary->ValueAt(entry); 4365 Object* result = dictionary->ValueAt(entry);
4367 PropertyDetails details = dictionary->DetailsAt(entry); 4366 PropertyDetails details = dictionary->DetailsAt(entry);
4368 // TODO(mstarzinger): We should check for details.IsDontDelete() here once 4367 // TODO(mstarzinger): We should check for details.IsDontDelete() here once
4369 // we only call into the runtime once to set both getter and setter. 4368 // we only call into the runtime once to set both getter and setter.
4370 if (details.type() == CALLBACKS && result->IsFixedArray()) { 4369 if (details.type() == CALLBACKS && result->IsAccessorPair()) {
4371 if (details.attributes() != attributes) { 4370 if (details.attributes() != attributes) {
4372 dictionary->DetailsAtPut(entry, 4371 dictionary->DetailsAtPut(entry,
4373 PropertyDetails(attributes, CALLBACKS, index)); 4372 PropertyDetails(attributes, CALLBACKS, index));
4374 } 4373 }
4375 return result; 4374 return result;
4376 } 4375 }
4377 } 4376 }
4378 return heap->the_hole_value(); 4377 return heap->the_hole_value();
4379 } 4378 }
4380 4379
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
4448 } else { 4447 } else {
4449 // Lookup the name. 4448 // Lookup the name.
4450 LookupResult result(heap->isolate()); 4449 LookupResult result(heap->isolate());
4451 LocalLookupRealNamedProperty(name, &result); 4450 LocalLookupRealNamedProperty(name, &result);
4452 if (result.IsProperty()) { 4451 if (result.IsProperty()) {
4453 // TODO(mstarzinger): We should check for result.IsDontDelete() here once 4452 // TODO(mstarzinger): We should check for result.IsDontDelete() here once
4454 // we only call into the runtime once to set both getter and setter. 4453 // we only call into the runtime once to set both getter and setter.
4455 if (result.type() == CALLBACKS) { 4454 if (result.type() == CALLBACKS) {
4456 Object* obj = result.GetCallbackObject(); 4455 Object* obj = result.GetCallbackObject();
4457 // Need to preserve old getters/setters. 4456 // Need to preserve old getters/setters.
4458 if (obj->IsFixedArray()) { 4457 if (obj->IsAccessorPair()) {
4459 // Use set to update attributes. 4458 // Use set to update attributes.
4460 return SetPropertyCallback(name, obj, attributes); 4459 return SetPropertyCallback(name, obj, attributes);
4461 } 4460 }
4462 } 4461 }
4463 } 4462 }
4464 } 4463 }
4465 4464
4466 // Allocate the fixed array to hold getter and setter. 4465 AccessorPair* accessors;
4467 Object* structure; 4466 { MaybeObject* maybe_accessors = heap->AllocateAccessorPair();
4468 { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED); 4467 if (!maybe_accessors->To<AccessorPair>(&accessors)) return maybe_accessors;
4469 if (!maybe_structure->ToObject(&structure)) return maybe_structure;
4470 } 4468 }
4471 4469
4472 if (is_element) { 4470 if (is_element) {
4473 return SetElementCallback(index, structure, attributes); 4471 return SetElementCallback(index, accessors, attributes);
4474 } else { 4472 } else {
4475 return SetPropertyCallback(name, structure, attributes); 4473 return SetPropertyCallback(name, accessors, attributes);
4476 } 4474 }
4477 } 4475 }
4478 4476
4479 4477
4480 bool JSObject::CanSetCallback(String* name) { 4478 bool JSObject::CanSetCallback(String* name) {
4481 ASSERT(!IsAccessCheckNeeded() || 4479 ASSERT(!IsAccessCheckNeeded() ||
4482 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); 4480 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4483 4481
4484 // Check if there is an API defined callback object which prohibits 4482 // Check if there is an API defined callback object which prohibits
4485 // callback overwriting in this object or it's prototype chain. 4483 // callback overwriting in this object or it's prototype chain.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
4601 } 4599 }
4602 4600
4603 if (IsJSGlobalProxy()) { 4601 if (IsJSGlobalProxy()) {
4604 Object* proto = GetPrototype(); 4602 Object* proto = GetPrototype();
4605 if (proto->IsNull()) return this; 4603 if (proto->IsNull()) return this;
4606 ASSERT(proto->IsJSGlobalObject()); 4604 ASSERT(proto->IsJSGlobalObject());
4607 return JSObject::cast(proto)->DefineAccessor(name, is_getter, 4605 return JSObject::cast(proto)->DefineAccessor(name, is_getter,
4608 fun, attributes); 4606 fun, attributes);
4609 } 4607 }
4610 4608
4611 Object* array; 4609 Object* accessors;
4612 { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); 4610 { MaybeObject* maybe_accessors = DefineGetterSetter(name, attributes);
4613 if (!maybe_array->ToObject(&array)) return maybe_array; 4611 if (!maybe_accessors->To<Object>(&accessors)) return maybe_accessors;
4614 } 4612 }
4615 if (array->IsUndefined()) return array; 4613 if (accessors->IsUndefined()) return accessors;
4616 FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); 4614 if (is_getter) {
4615 AccessorPair::cast(accessors)->set_getter(fun);
4616 } else {
4617 AccessorPair::cast(accessors)->set_setter(fun);
4618 }
4617 return this; 4619 return this;
4618 } 4620 }
4619 4621
4620 4622
4621 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { 4623 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
4622 Isolate* isolate = GetIsolate(); 4624 Isolate* isolate = GetIsolate();
4623 String* name = String::cast(info->name()); 4625 String* name = String::cast(info->name());
4624 // Check access rights if needed. 4626 // Check access rights if needed.
4625 if (IsAccessCheckNeeded() && 4627 if (IsAccessCheckNeeded() &&
4626 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 4628 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
4710 AssertNoContextChange ncc; 4712 AssertNoContextChange ncc;
4711 4713
4712 // Check access rights if needed. 4714 // Check access rights if needed.
4713 if (IsAccessCheckNeeded() && 4715 if (IsAccessCheckNeeded() &&
4714 !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { 4716 !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
4715 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 4717 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
4716 return heap->undefined_value(); 4718 return heap->undefined_value();
4717 } 4719 }
4718 4720
4719 // Make the lookup and include prototypes. 4721 // Make the lookup and include prototypes.
4720 // Introducing constants below makes static constants usage purely static
4721 // and avoids linker errors in debug build using gcc.
4722 const int getter_index = kGetterIndex;
4723 const int setter_index = kSetterIndex;
4724 int accessor_index = is_getter ? getter_index : setter_index;
4725 uint32_t index = 0; 4722 uint32_t index = 0;
4726 if (name->AsArrayIndex(&index)) { 4723 if (name->AsArrayIndex(&index)) {
4727 for (Object* obj = this; 4724 for (Object* obj = this;
4728 obj != heap->null_value(); 4725 obj != heap->null_value();
4729 obj = JSObject::cast(obj)->GetPrototype()) { 4726 obj = JSObject::cast(obj)->GetPrototype()) {
4730 JSObject* js_object = JSObject::cast(obj); 4727 JSObject* js_object = JSObject::cast(obj);
4731 if (js_object->HasDictionaryElements()) { 4728 if (js_object->HasDictionaryElements()) {
4732 NumberDictionary* dictionary = js_object->element_dictionary(); 4729 NumberDictionary* dictionary = js_object->element_dictionary();
4733 int entry = dictionary->FindEntry(index); 4730 int entry = dictionary->FindEntry(index);
4734 if (entry != NumberDictionary::kNotFound) { 4731 if (entry != NumberDictionary::kNotFound) {
4735 Object* element = dictionary->ValueAt(entry); 4732 Object* element = dictionary->ValueAt(entry);
4736 PropertyDetails details = dictionary->DetailsAt(entry); 4733 PropertyDetails details = dictionary->DetailsAt(entry);
4737 if (details.type() == CALLBACKS) { 4734 if (details.type() == CALLBACKS) {
4738 if (element->IsFixedArray()) { 4735 if (element->IsAccessorPair()) {
4739 return FixedArray::cast(element)->get(accessor_index); 4736 AccessorPair* accessors = AccessorPair::cast(element);
4737 return is_getter ? accessors->getter() : accessors->setter();
4740 } 4738 }
4741 } 4739 }
4742 } 4740 }
4743 } 4741 }
4744 } 4742 }
4745 } else { 4743 } else {
4746 for (Object* obj = this; 4744 for (Object* obj = this;
4747 obj != heap->null_value(); 4745 obj != heap->null_value();
4748 obj = JSObject::cast(obj)->GetPrototype()) { 4746 obj = JSObject::cast(obj)->GetPrototype()) {
4749 LookupResult result(heap->isolate()); 4747 LookupResult result(heap->isolate());
4750 JSObject::cast(obj)->LocalLookup(name, &result); 4748 JSObject::cast(obj)->LocalLookup(name, &result);
4751 if (result.IsProperty()) { 4749 if (result.IsProperty()) {
4752 if (result.IsReadOnly()) return heap->undefined_value(); 4750 if (result.IsReadOnly()) return heap->undefined_value();
4753 if (result.type() == CALLBACKS) { 4751 if (result.type() == CALLBACKS) {
4754 Object* obj = result.GetCallbackObject(); 4752 Object* obj = result.GetCallbackObject();
4755 if (obj->IsFixedArray()) { 4753 if (obj->IsAccessorPair()) {
4756 return FixedArray::cast(obj)->get(accessor_index); 4754 AccessorPair* accessors = AccessorPair::cast(obj);
4755 return is_getter ? accessors->getter() : accessors->setter();
4757 } 4756 }
4758 } 4757 }
4759 } 4758 }
4760 } 4759 }
4761 } 4760 }
4762 return heap->undefined_value(); 4761 return heap->undefined_value();
4763 } 4762 }
4764 4763
4765 4764
4766 Object* JSObject::SlowReverseLookup(Object* value) { 4765 Object* JSObject::SlowReverseLookup(Object* value) {
(...skipping 4286 matching lines...) Expand 10 before | Expand all | Expand 10 after
9053 // Leaving JavaScript. 9052 // Leaving JavaScript.
9054 VMState state(isolate, EXTERNAL); 9053 VMState state(isolate, EXTERNAL);
9055 result = call_fun(v8::Utils::ToLocal(key), info); 9054 result = call_fun(v8::Utils::ToLocal(key), info);
9056 } 9055 }
9057 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 9056 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9058 if (result.IsEmpty()) return isolate->heap()->undefined_value(); 9057 if (result.IsEmpty()) return isolate->heap()->undefined_value();
9059 return *v8::Utils::OpenHandle(*result); 9058 return *v8::Utils::OpenHandle(*result);
9060 } 9059 }
9061 9060
9062 // __defineGetter__ callback 9061 // __defineGetter__ callback
9063 if (structure->IsFixedArray()) { 9062 if (structure->IsAccessorPair()) {
9064 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); 9063 Object* getter = AccessorPair::cast(structure)->getter();
9065 if (getter->IsSpecFunction()) { 9064 if (getter->IsSpecFunction()) {
9066 // TODO(rossberg): nicer would be to cast to some JSCallable here... 9065 // TODO(rossberg): nicer would be to cast to some JSCallable here...
9067 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); 9066 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
9068 } 9067 }
9069 // Getter is not a function. 9068 // Getter is not a function.
9070 return isolate->heap()->undefined_value(); 9069 return isolate->heap()->undefined_value();
9071 } 9070 }
9072 9071
9073 UNREACHABLE(); 9072 UNREACHABLE();
9074 return NULL; 9073 return NULL;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
9110 // Leaving JavaScript. 9109 // Leaving JavaScript.
9111 VMState state(isolate, EXTERNAL); 9110 VMState state(isolate, EXTERNAL);
9112 call_fun(v8::Utils::ToLocal(key), 9111 call_fun(v8::Utils::ToLocal(key),
9113 v8::Utils::ToLocal(value_handle), 9112 v8::Utils::ToLocal(value_handle),
9114 info); 9113 info);
9115 } 9114 }
9116 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 9115 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
9117 return *value_handle; 9116 return *value_handle;
9118 } 9117 }
9119 9118
9120 if (structure->IsFixedArray()) { 9119 if (structure->IsAccessorPair()) {
9121 Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex)); 9120 Handle<Object> setter(AccessorPair::cast(structure)->setter());
9122 if (setter->IsSpecFunction()) { 9121 if (setter->IsSpecFunction()) {
9123 // TODO(rossberg): nicer would be to cast to some JSCallable here... 9122 // TODO(rossberg): nicer would be to cast to some JSCallable here...
9124 return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value); 9123 return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
9125 } else { 9124 } else {
9126 if (strict_mode == kNonStrictMode) { 9125 if (strict_mode == kNonStrictMode) {
9127 return value; 9126 return value;
9128 } 9127 }
9129 Handle<Object> holder_handle(holder, isolate); 9128 Handle<Object> holder_handle(holder, isolate);
9130 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); 9129 Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
9131 Handle<Object> args[2] = { key, holder_handle }; 9130 Handle<Object> args[2] = { key, holder_handle };
(...skipping 3610 matching lines...) Expand 10 before | Expand all | Expand 10 after
12742 if (break_point_objects()->IsUndefined()) return 0; 12741 if (break_point_objects()->IsUndefined()) return 0;
12743 // Single break point. 12742 // Single break point.
12744 if (!break_point_objects()->IsFixedArray()) return 1; 12743 if (!break_point_objects()->IsFixedArray()) return 1;
12745 // Multiple break points. 12744 // Multiple break points.
12746 return FixedArray::cast(break_point_objects())->length(); 12745 return FixedArray::cast(break_point_objects())->length();
12747 } 12746 }
12748 #endif // ENABLE_DEBUGGER_SUPPORT 12747 #endif // ENABLE_DEBUGGER_SUPPORT
12749 12748
12750 12749
12751 } } // namespace v8::internal 12750 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698