Revision: 10371
Author: [email protected]
Date: Tue Jan 10 08:11:33 2012
Log: Use a separate new type AccessorPair for JavaScript callbacks
instead of a FixedArray of length 2
http://code.google.com/p/v8/source/detail?r=10371
Modified:
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/factory.cc
/branches/bleeding_edge/src/factory.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/profile-generator.cc
/branches/bleeding_edge/src/runtime.cc
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Jan 5 09:16:19 2012
+++ /branches/bleeding_edge/src/bootstrapper.cc Tue Jan 10 08:11:33 2012
@@ -264,13 +264,13 @@
Handle<Map> CreateStrictModeFunctionMap(
PrototypePropertyMode prototype_mode,
Handle<JSFunction> empty_function,
- Handle<FixedArray> arguments_callbacks,
- Handle<FixedArray> caller_callbacks);
+ Handle<AccessorPair> arguments_callbacks,
+ Handle<AccessorPair> caller_callbacks);
Handle<DescriptorArray> ComputeStrictFunctionInstanceDescriptor(
PrototypePropertyMode propertyMode,
- Handle<FixedArray> arguments,
- Handle<FixedArray> caller);
+ Handle<AccessorPair> arguments,
+ Handle<AccessorPair> caller);
static bool CompileBuiltin(Isolate* isolate, int index);
static bool CompileExperimentalBuiltin(Isolate* isolate, int index);
@@ -540,8 +540,8 @@
Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor(
PrototypePropertyMode prototypeMode,
- Handle<FixedArray> arguments,
- Handle<FixedArray> caller) {
+ Handle<AccessorPair> arguments,
+ Handle<AccessorPair> caller) {
Handle<DescriptorArray> descriptors =
factory()->NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE
? 4
@@ -611,8 +611,8 @@
Handle<Map> Genesis::CreateStrictModeFunctionMap(
PrototypePropertyMode prototype_mode,
Handle<JSFunction> empty_function,
- Handle<FixedArray> arguments_callbacks,
- Handle<FixedArray> caller_callbacks) {
+ Handle<AccessorPair> arguments_callbacks,
+ Handle<AccessorPair> caller_callbacks) {
Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
Handle<DescriptorArray> descriptors =
ComputeStrictFunctionInstanceDescriptor(prototype_mode,
@@ -629,8 +629,8 @@
// Create the callbacks arrays for ThrowTypeError functions.
// The get/set callacks are filled in after the maps are created below.
Factory* factory = empty->GetIsolate()->factory();
- Handle<FixedArray> arguments = factory->NewFixedArray(2, TENURED);
- Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED);
+ Handle<AccessorPair> arguments(factory->NewAccessorPair());
+ Handle<AccessorPair> caller(factory->NewAccessorPair());
// Allocate map for the strict mode function instances.
Handle<Map> strict_mode_function_instance_map =
@@ -665,11 +665,11 @@
Handle<JSFunction> throw_function =
GetThrowTypeErrorFunction();
- // Complete the callback fixed arrays.
- arguments->set(0, *throw_function);
- arguments->set(1, *throw_function);
- caller->set(0, *throw_function);
- caller->set(1, *throw_function);
+ // Complete the callbacks.
+ arguments->set_getter(*throw_function);
+ arguments->set_setter(*throw_function);
+ caller->set_getter(*throw_function);
+ caller->set_setter(*throw_function);
}
@@ -1142,17 +1142,17 @@
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
// Create the ThrowTypeError functions.
- Handle<FixedArray> callee = factory->NewFixedArray(2, TENURED);
- Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED);
+ Handle<AccessorPair> callee = factory->NewAccessorPair();
+ Handle<AccessorPair> caller = factory->NewAccessorPair();
Handle<JSFunction> throw_function =
GetThrowTypeErrorFunction();
// Install the ThrowTypeError functions.
- callee->set(0, *throw_function);
- callee->set(1, *throw_function);
- caller->set(0, *throw_function);
- caller->set(1, *throw_function);
+ callee->set_getter(*throw_function);
+ callee->set_setter(*throw_function);
+ caller->set_getter(*throw_function);
+ caller->set_setter(*throw_function);
// Create the descriptor array for the arguments object.
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3);
=======================================
--- /branches/bleeding_edge/src/factory.cc Thu Jan 5 09:16:19 2012
+++ /branches/bleeding_edge/src/factory.cc Tue Jan 10 08:11:33 2012
@@ -129,6 +129,13 @@
pretenure),
DeoptimizationOutputData);
}
+
+
+Handle<AccessorPair> Factory::NewAccessorPair() {
+ CALL_HEAP_FUNCTION(isolate(),
+ isolate()->heap()->AllocateAccessorPair(),
+ AccessorPair);
+}
// Symbols are created in the old generation (data space).
=======================================
--- /branches/bleeding_edge/src/factory.h Fri Dec 9 00:50:19 2011
+++ /branches/bleeding_edge/src/factory.h Tue Jan 10 08:11:33 2012
@@ -69,6 +69,7 @@
Handle<DeoptimizationOutputData> NewDeoptimizationOutputData(
int deopt_entry_count,
PretenureFlag pretenure);
+ Handle<AccessorPair> NewAccessorPair();
Handle<String> LookupSymbol(Vector<const char> str);
Handle<String> LookupSymbol(Handle<String> str);
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/heap.cc Tue Jan 10 08:11:33 2012
@@ -1867,6 +1867,19 @@
MaybeObject* Heap::AllocatePolymorphicCodeCache() {
return AllocateStruct(POLYMORPHIC_CODE_CACHE_TYPE);
}
+
+
+MaybeObject* Heap::AllocateAccessorPair() {
+ Object* result;
+ { MaybeObject* maybe_result = AllocateStruct(ACCESSOR_PAIR_TYPE);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ AccessorPair* accessors = AccessorPair::cast(result);
+ // Later we will have to distinguish between undefined and the hole...
+ // accessors->set_getter(the_hole_value(), SKIP_WRITE_BARRIER);
+ // accessors->set_setter(the_hole_value(), SKIP_WRITE_BARRIER);
+ return accessors;
+}
const Heap::StringTypeTable Heap::string_type_table[] = {
=======================================
--- /branches/bleeding_edge/src/heap.h Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/heap.h Tue Jan 10 08:11:33 2012
@@ -615,6 +615,9 @@
// Allocates an empty PolymorphicCodeCache.
MUST_USE_RESULT MaybeObject* AllocatePolymorphicCodeCache();
+ // Allocates an empty AccessorPair.
+ MaybeObject* AllocateAccessorPair();
+
// Clear the Instanceof cache (used when a prototype changes).
inline void ClearInstanceofCache();
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Tue Oct 25 07:14:56 2011
+++ /branches/bleeding_edge/src/objects-debug.cc Tue Jan 10 08:11:33 2012
@@ -600,6 +600,13 @@
VerifyPointer(data());
VerifyPointer(flag());
}
+
+
+void AccessorPair::AccessorPairVerify() {
+ CHECK(IsAccessorPair());
+ VerifyPointer(getter());
+ VerifyPointer(setter());
+}
void AccessCheckInfo::AccessCheckInfoVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/objects-inl.h Tue Jan 10 08:11:33 2012
@@ -3386,6 +3386,9 @@
ACCESSORS(AccessorInfo, name, Object, kNameOffset)
ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
+ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
+ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
+
ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
ACCESSORS(AccessCheckInfo, indexed_callback, Object,
kIndexedCallbackOffset)
ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Wed Nov 23 05:08:28 2011
+++ /branches/bleeding_edge/src/objects-printer.cc Tue Jan 10 08:11:33 2012
@@ -784,6 +784,15 @@
PrintF(out, "\n - flag: ");
flag()->ShortPrint(out);
}
+
+
+void AccessorPair::AccessorPairPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "AccessorPair");
+ PrintF(out, "\n - getter: ");
+ getter()->ShortPrint(out);
+ PrintF(out, "\n - setter: ");
+ setter()->ShortPrint(out);
+}
void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
=======================================
--- /branches/bleeding_edge/src/objects.cc Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/objects.cc Tue Jan 10 08:11:33 2012
@@ -246,8 +246,8 @@
}
// __defineGetter__ callback
- if (structure->IsFixedArray()) {
- Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
+ if (structure->IsAccessorPair()) {
+ Object* getter = AccessorPair::cast(structure)->getter();
if (getter->IsSpecFunction()) {
// TODO(rossberg): nicer would be to cast to some JSCallable here...
return GetPropertyWithDefinedGetter(receiver,
JSReceiver::cast(getter));
@@ -2039,8 +2039,8 @@
return *value_handle;
}
- if (structure->IsFixedArray()) {
- Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
+ if (structure->IsAccessorPair()) {
+ Object* setter = AccessorPair::cast(structure)->setter();
if (setter->IsSpecFunction()) {
// TODO(rossberg): nicer would be to cast to some JSCallable here...
return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
@@ -4353,10 +4353,9 @@
// Search for a getter or setter in an elements dictionary and update its
-// attributes. Returns either undefined if the element is non-deletable,
or
-// the getter/setter pair (fixed array) if there is an existing one, or the
-// hole value if the element does not exist or is a normal
non-getter/setter
-// data element.
+// attributes. Returns either undefined if the element is non-deletable,
or the
+// getter/setter pair if there is an existing one, or the hole value if the
+// element does not exist or is a normal non-getter/setter data element.
static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary,
uint32_t index,
PropertyAttributes
attributes,
@@ -4367,7 +4366,7 @@
PropertyDetails details = dictionary->DetailsAt(entry);
// TODO(mstarzinger): We should check for details.IsDontDelete() here
once
// we only call into the runtime once to set both getter and setter.
- if (details.type() == CALLBACKS && result->IsFixedArray()) {
+ if (details.type() == CALLBACKS && result->IsAccessorPair()) {
if (details.attributes() != attributes) {
dictionary->DetailsAtPut(entry,
PropertyDetails(attributes, CALLBACKS,
index));
@@ -4455,7 +4454,7 @@
if (result.type() == CALLBACKS) {
Object* obj = result.GetCallbackObject();
// Need to preserve old getters/setters.
- if (obj->IsFixedArray()) {
+ if (obj->IsAccessorPair()) {
// Use set to update attributes.
return SetPropertyCallback(name, obj, attributes);
}
@@ -4463,16 +4462,15 @@
}
}
- // Allocate the fixed array to hold getter and setter.
- Object* structure;
- { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED);
- if (!maybe_structure->ToObject(&structure)) return maybe_structure;
+ AccessorPair* accessors;
+ { MaybeObject* maybe_accessors = heap->AllocateAccessorPair();
+ if (!maybe_accessors->To<AccessorPair>(&accessors)) return
maybe_accessors;
}
if (is_element) {
- return SetElementCallback(index, structure, attributes);
+ return SetElementCallback(index, accessors, attributes);
} else {
- return SetPropertyCallback(name, structure, attributes);
+ return SetPropertyCallback(name, accessors, attributes);
}
}
@@ -4608,12 +4606,15 @@
fun, attributes);
}
- Object* array;
- { MaybeObject* maybe_array = DefineGetterSetter(name, attributes);
- if (!maybe_array->ToObject(&array)) return maybe_array;
- }
- if (array->IsUndefined()) return array;
- FixedArray::cast(array)->set(is_getter ? 0 : 1, fun);
+ AccessorPair* accessors;
+ { MaybeObject* maybe_accessors = DefineGetterSetter(name, attributes);
+ if (!maybe_accessors->To<AccessorPair>(&accessors)) return
maybe_accessors;
+ }
+ if (is_getter) {
+ accessors->set_getter(fun);
+ } else {
+ accessors->set_setter(fun);
+ }
return this;
}
@@ -4717,11 +4718,6 @@
}
// Make the lookup and include prototypes.
- // Introducing constants below makes static constants usage purely static
- // and avoids linker errors in debug build using gcc.
- const int getter_index = kGetterIndex;
- const int setter_index = kSetterIndex;
- int accessor_index = is_getter ? getter_index : setter_index;
uint32_t index = 0;
if (name->AsArrayIndex(&index)) {
for (Object* obj = this;
@@ -4735,8 +4731,9 @@
Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
- if (element->IsFixedArray()) {
- return FixedArray::cast(element)->get(accessor_index);
+ if (element->IsAccessorPair()) {
+ AccessorPair *accessors = AccessorPair::cast(element);
+ return is_getter ? accessors->getter() : accessors->setter();
}
}
}
@@ -4752,8 +4749,9 @@
if (result.IsReadOnly()) return heap->undefined_value();
if (result.type() == CALLBACKS) {
Object* obj = result.GetCallbackObject();
- if (obj->IsFixedArray()) {
- return FixedArray::cast(obj)->get(accessor_index);
+ if (obj->IsAccessorPair()) {
+ AccessorPair *accessors = AccessorPair::cast(obj);
+ return is_getter ? accessors->getter() : accessors->setter();
}
}
}
@@ -9060,8 +9058,8 @@
}
// __defineGetter__ callback
- if (structure->IsFixedArray()) {
- Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
+ if (structure->IsAccessorPair()) {
+ Object* getter = AccessorPair::cast(structure)->getter();
if (getter->IsSpecFunction()) {
// TODO(rossberg): nicer would be to cast to some JSCallable here...
return GetPropertyWithDefinedGetter(receiver,
JSReceiver::cast(getter));
@@ -9117,8 +9115,8 @@
return *value_handle;
}
- if (structure->IsFixedArray()) {
- Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex));
+ if (structure->IsAccessorPair()) {
+ Handle<Object> setter(AccessorPair::cast(structure)->setter());
if (setter->IsSpecFunction()) {
// TODO(rossberg): nicer would be to cast to some JSCallable here...
return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter),
value);
=======================================
--- /branches/bleeding_edge/src/objects.h Tue Jan 10 05:24:18 2012
+++ /branches/bleeding_edge/src/objects.h Tue Jan 10 08:11:33 2012
@@ -107,6 +107,7 @@
// - SharedFunctionInfo
// - Struct
// - AccessorInfo
+// - AccessorPair
// - AccessCheckInfo
// - InterceptorInfo
// - CallHandlerInfo
@@ -275,6 +276,7 @@
V(FILLER_TYPE)
\
\
V(ACCESSOR_INFO_TYPE)
\
+
V(ACCESSOR_PAIR_TYPE)
\
V(ACCESS_CHECK_INFO_TYPE)
\
V(INTERCEPTOR_INFO_TYPE)
\
V(CALL_HANDLER_INFO_TYPE)
\
@@ -422,6 +424,7 @@
// manually.
#define
STRUCT_LIST_ALL(V) \
V(ACCESSOR_INFO, AccessorInfo,
accessor_info) \
+ V(ACCESSOR_PAIR, AccessorPair,
accessor_pair) \
V(ACCESS_CHECK_INFO, AccessCheckInfo,
access_check_info) \
V(INTERCEPTOR_INFO, InterceptorInfo,
interceptor_info) \
V(CALL_HANDLER_INFO, CallHandlerInfo,
call_handler_info) \
@@ -575,6 +578,7 @@
// Structs.
ACCESSOR_INFO_TYPE,
+ ACCESSOR_PAIR_TYPE,
ACCESS_CHECK_INFO_TYPE,
INTERCEPTOR_INFO_TYPE,
CALL_HANDLER_INFO_TYPE,
@@ -2006,11 +2010,6 @@
#endif
Object* SlowReverseLookup(Object* value);
- // Getters and setters are stored in a fixed array property.
- // These are constants for their indices.
- static const int kGetterIndex = 0;
- static const int kSetterIndex = 1;
-
// Maximal number of fast properties for the JSObject. Used to
// restrict the number of map transitions to avoid an explosion in
// the number of maps for objects used as dictionaries.
@@ -7636,6 +7635,35 @@
};
+// Support for JavaScript accessors: A pair of a getter and a setter. Each
+// accessor can either be
+// * a pointer to a JavaScript function or proxy: a real accessor
+// * undefined: considered an accessor by the spec, too, strangely enough
+// * the hole: an accessor which has not been set
+// * a pointer to a map: a transition used to ensure map sharing
+class AccessorPair: public Struct {
+ public:
+ DECL_ACCESSORS(getter, Object)
+ DECL_ACCESSORS(setter, Object)
+
+ static inline AccessorPair* cast(Object* obj);
+
+#ifdef OBJECT_PRINT
+ void AccessorPairPrint(FILE* out = stdout);
+#endif
+#ifdef DEBUG
+ void AccessorPairVerify();
+#endif
+
+ static const int kGetterOffset = HeapObject::kHeaderSize;
+ static const int kSetterOffset = kGetterOffset + kPointerSize;
+ static const int kSize = kSetterOffset + kPointerSize;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair);
+};
+
+
class AccessCheckInfo: public Struct {
public:
DECL_ACCESSORS(named_callback, Object)
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Jan 10 05:24:18
2012
+++ /branches/bleeding_edge/src/profile-generator.cc Tue Jan 10 08:11:33
2012
@@ -2230,13 +2230,13 @@
break;
case CALLBACKS: {
Object* callback_obj = descs->GetValue(i);
- if (callback_obj->IsFixedArray()) {
- FixedArray* accessors = FixedArray::cast(callback_obj);
- if (Object* getter = accessors->get(JSObject::kGetterIndex)) {
+ if (callback_obj->IsAccessorPair()) {
+ AccessorPair* accessors = AccessorPair::cast(callback_obj);
+ if (Object* getter = accessors->getter()) {
SetPropertyReference(js_obj, entry, descs->GetKey(i),
getter, "get-%s");
}
- if (Object* setter = accessors->get(JSObject::kSetterIndex)) {
+ if (Object* setter = accessors->setter()) {
SetPropertyReference(js_obj, entry, descs->GetKey(i),
setter, "set-%s");
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Jan 10 08:06:32 2012
+++ /branches/bleeding_edge/src/runtime.cc Tue Jan 10 08:11:33 2012
@@ -1056,14 +1056,14 @@
switch (details.type()) {
case CALLBACKS: {
// This is an accessor property with getter and/or setter.
- FixedArray* callbacks =
- FixedArray::cast(dictionary->ValueAt(entry));
+ AccessorPair* accessors =
+ AccessorPair::cast(dictionary->ValueAt(entry));
elms->set(IS_ACCESSOR_INDEX, heap->true_value());
if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
- elms->set(GETTER_INDEX, callbacks->get(0));
+ elms->set(GETTER_INDEX, accessors->getter());
}
if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
- elms->set(SETTER_INDEX, callbacks->get(1));
+ elms->set(SETTER_INDEX, accessors->setter());
}
break;
}
@@ -1102,18 +1102,18 @@
elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
bool is_js_accessor = (result.type() == CALLBACKS) &&
- (result.GetCallbackObject()->IsFixedArray());
+ (result.GetCallbackObject()->IsAccessorPair());
if (is_js_accessor) {
// __defineGetter__/__defineSetter__ callback.
elms->set(IS_ACCESSOR_INDEX, heap->true_value());
- FixedArray* structure = FixedArray::cast(result.GetCallbackObject());
+ AccessorPair* accessors =
AccessorPair::cast(result.GetCallbackObject());
if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
- elms->set(GETTER_INDEX, structure->get(0));
+ elms->set(GETTER_INDEX, accessors->getter());
}
if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
- elms->set(SETTER_INDEX, structure->get(1));
+ elms->set(SETTER_INDEX, accessors->setter());
}
} else {
elms->set(IS_ACCESSOR_INDEX, heap->false_value());
@@ -10474,15 +10474,15 @@
// If the callback object is a fixed array then it contains
JavaScript
// getter and/or setter.
bool hasJavaScriptAccessors = result_type == CALLBACKS &&
- result_callback_obj->IsFixedArray();
+ result_callback_obj->IsAccessorPair();
Handle<FixedArray> details =
isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 :
2);
details->set(0, *value);
details->set(1, property_details);
if (hasJavaScriptAccessors) {
details->set(2, isolate->heap()->ToBoolean(caught_exception));
- details->set(3, FixedArray::cast(*result_callback_obj)->get(0));
- details->set(4, FixedArray::cast(*result_callback_obj)->get(1));
+ details->set(3,
AccessorPair::cast(*result_callback_obj)->getter());
+ details->set(4,
AccessorPair::cast(*result_callback_obj)->setter());
}
return *isolate->factory()->NewJSArrayWithElements(details);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev