// If we don't know the monomorphic type, do a generic store.
CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value));
} else {
+#if DEBUG
+ Handle<AccessorPair> accessors;
+ Handle<JSObject> holder;
+ ASSERT(!LookupAccessorPair(map, name, &accessors, &holder));
+#endif
CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal,
name,
value,
return BuildStoreNamedField(object, name, value, map, &lookup, true);
}
- // Handle a known setter directly in the receiver.
- map->LookupDescriptor(NULL, *name, &lookup);
- if (lookup.IsPropertyCallbacks()) {
- Handle<Object> callback(lookup.GetValueFromMap(*map));
- Handle<JSObject> holder;
- if (!callback->IsAccessorPair()) {
- return BuildStoreNamedGeneric(object, name, value);
- }
- Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback);
- return BuildCallSetter(object, value, map, accessors, holder);
- }
-
- // Handle a known setter somewhere in the prototype chain.
- LookupInPrototypes(map, name, &lookup);
- if (lookup.IsPropertyCallbacks()) {
- Handle<Object> callback(lookup.GetValue());
- Handle<JSObject> holder(lookup.holder());
- if (!callback->IsAccessorPair()) {
- return BuildStoreNamedGeneric(object, name, value);
- }
- Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback);
- return BuildCallSetter(object, value, map, accessors, holder);
- }
-
// No luck, do a generic store.
return BuildStoreNamedGeneric(object, name, value);
}
SmallMapList* types = expr->GetReceiverTypes();
if (expr->IsMonomorphic()) {
Handle<Map> map = types->first();
- CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, name, value, map));
+ Handle<AccessorPair> accessors;
+ Handle<JSObject> holder;
+ if (LookupAccessorPair(map, name, &accessors, &holder)) {
+ instr = BuildCallSetter(object, value, map, accessors, holder);
+ } else {
+ CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
+ name,
+ value,
+ map));
+ }
} else if (types != NULL && types->length() > 1) {
HandlePolymorphicStoreNamedField(expr, object, value, types, name);
return;
HInstruction* load;
if (prop->IsMonomorphic()) {
map = prop->GetReceiverTypes()->first();
- load = BuildLoadNamedMonomorphic(object, name, prop, map);
+ Handle<AccessorPair> accessors;
+ Handle<JSObject> holder;
+ if (LookupAccessorPair(map, name, &accessors, &holder)) {
+ load = BuildCallGetter(object, map, accessors, holder);
+ } else {
+ load = BuildLoadNamedMonomorphic(object, name, prop, map);
+ }
} else {
load = BuildLoadNamedGeneric(object, name, prop);
}
// If we don't know the monomorphic type, do a generic store.
CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr));
} else {
- CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
- name,
- instr,
- map));
+ Handle<AccessorPair> accessors;
+ Handle<JSObject> holder;
+ if (LookupAccessorPair(map, name, &accessors, &holder)) {
+ store = BuildCallSetter(object, instr, map, accessors, holder);
+ } else {
+ CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
+ name,
+ instr,
+ map));
+ }
}
AddInstruction(store);
// Drop the simulated receiver and value. Return the value.
}
+bool HGraphBuilder::LookupAccessorPair(Handle<Map> map,
+ Handle<String> name,
+ Handle<AccessorPair>* accessors,
+ Handle<JSObject>* holder) {
+ LookupResult lookup(isolate());
+
+ // Check for a JavaScript accessor directly in the map.
+ map->LookupDescriptor(NULL, *name, &lookup);
+ if (lookup.IsPropertyCallbacks()) {
+ Handle<Object> callback(lookup.GetValueFromMap(*map));
+ if (!callback->IsAccessorPair()) return false;
+ *accessors = Handle<AccessorPair>::cast(callback);
+ *holder = Handle<JSObject>();
+ return true;
+ }
+
+ // Everything else, e.g. a field, can't be an accessor call.
+ if (lookup.IsFound()) return false;
+
+ // Check for a JavaScript accessor somewhere in the proto chain.
+ LookupInPrototypes(map, name, &lookup);
+ if (lookup.IsPropertyCallbacks()) {
+ Handle<Object> callback(lookup.GetValue());
+ if (!callback->IsAccessorPair()) return false;
+ *accessors = Handle<AccessorPair>::cast(callback);
+ *holder = Handle<JSObject>(lookup.holder());
+ return true;
+ }
+
+ // We haven't found a JavaScript accessor anywhere.
+ return false;
+}
+
+
HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object,
Handle<String> name,
Property* expr,
return new(zone()) HConstant(function, Representation::Tagged());
}
- // Handle a known getter directly in the receiver.
- if (lookup.IsPropertyCallbacks()) {
- Handle<Object> callback(lookup.GetValueFromMap(*map));
- Handle<JSObject> holder;
- if (!callback->IsAccessorPair()) {
- return BuildLoadNamedGeneric(object, name, expr);
- }
- Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback);
- return BuildCallGetter(object, map, accessors, holder);
- }
-
- // Handle a known getter somewhere in the prototype chain.
- LookupInPrototypes(map, name, &lookup);
- if (lookup.IsPropertyCallbacks()) {
- Handle<Object> callback(lookup.GetValue());
- Handle<JSObject> holder(lookup.holder());
- if (!callback->IsAccessorPair()) {
- return BuildLoadNamedGeneric(object, name, expr);
- }
- Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback);
- return BuildCallGetter(object, map, accessors, holder);
- }
-
// No luck, do a generic load.
return BuildLoadNamedGeneric(object, name, expr);
}
HValue* obj = Pop();
if (expr->IsMonomorphic()) {
- instr = BuildLoadNamedMonomorphic(obj, name, expr, types->first());
+ Handle<Map> map = types->first();
+ Handle<AccessorPair> accessors;
+ Handle<JSObject> holder;
+ if (LookupAccessorPair(map, name, &accessors, &holder)) {
+ instr = BuildCallGetter(obj, map, accessors, holder);
+ } else {
+ instr = BuildLoadNamedMonomorphic(obj, name, expr, map);
+ }
} else if (types != NULL && types->length() > 1) {
AddInstruction(new(zone()) HCheckNonSmi(obj));
HandlePolymorphicLoadNamedField(expr, obj, types, name);
HInstruction* load;
if (prop->IsMonomorphic()) {
map = prop->GetReceiverTypes()->first();
- load = BuildLoadNamedMonomorphic(object, name, prop, map);
+ Handle<AccessorPair> accessors;
+ Handle<JSObject> holder;
+ if (LookupAccessorPair(map, name, &accessors, &holder)) {
+ load = BuildCallGetter(object, map, accessors, holder);
+ } else {
+ load = BuildLoadNamedMonomorphic(object, name, prop, map);
+ }
} else {
load = BuildLoadNamedGeneric(object, name, prop);
}
// If we don't know the monomorphic type, do a generic store.
CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after));
} else {
- CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
- name,
- after,
- map));
+ Handle<AccessorPair> accessors;
+ Handle<JSObject> holder;
+ if (LookupAccessorPair(map, name, &accessors, &holder)) {
+ store = BuildCallSetter(object, after, map, accessors, holder);
+ } else {
+ CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
+ name,
+ after,
+ map));
+ }
}
AddInstruction(store);
HValue* right);
HInstruction* BuildIncrement(bool returns_original_input,
CountOperation* expr);
- HLoadNamedField* BuildLoadNamedField(HValue* object,
- Handle<Map> map,
- LookupResult* result,
- bool smi_and_map_check);
- HInstruction* BuildLoadNamedGeneric(HValue* object,
- Handle<String> name,
- Property* expr);
- HInstruction* BuildLoadKeyedGeneric(HValue* object, HValue* key);
- HInstruction* BuildExternalArrayElementAccess(
- HValue* external_elements,
- HValue* checked_key,
- HValue* val,
- HValue* dependency,
- ElementsKind elements_kind,
- bool is_store);
HInstruction* BuildFastElementAccess(HValue* elements,
HValue* checked_key,
HValue* val,
bool is_store,
bool* has_side_effects);
+ // Tries to find a JavaScript accessor of the given name in the prototype
+ // chain starting at the given map. Return true iff there is one, including
+ // the corresponding AccessorPair plus its holder (which could be null when
+ // the accessor is found directly in the given map).
+ bool LookupAccessorPair(Handle<Map> map,
+ Handle<String> name,
+ Handle<AccessorPair>* accessors,
+ Handle<JSObject>* holder);
+
+ HLoadNamedField* BuildLoadNamedField(HValue* object,
+ Handle<Map> map,
+ LookupResult* result,
+ bool smi_and_map_check);
+ HInstruction* BuildLoadNamedGeneric(HValue* object,
+ Handle<String> name,
+ Property* expr);
HInstruction* BuildCallGetter(HValue* object,
Handle<Map> map,
Handle<AccessorPair> accessors,
Handle<String> name,
Property* expr,
Handle<Map> map);
- HInstruction* BuildCallSetter(HValue* object,
- HValue* value,
- Handle<Map> map,
- Handle<AccessorPair> accessors,
- Handle<JSObject> holder);
- HInstruction* BuildStoreNamedMonomorphic(HValue* object,
- Handle<String> name,
- HValue* value,
- Handle<Map> map);
+ HInstruction* BuildLoadKeyedGeneric(HValue* object, HValue* key);
+ HInstruction* BuildExternalArrayElementAccess(
+ HValue* external_elements,
+ HValue* checked_key,
+ HValue* val,
+ HValue* dependency,
+ ElementsKind elements_kind,
+ bool is_store);
+
HInstruction* BuildStoreNamedField(HValue* object,
Handle<String> name,
HValue* value,
HInstruction* BuildStoreNamedGeneric(HValue* object,
Handle<String> name,
HValue* value);
+ HInstruction* BuildCallSetter(HValue* object,
+ HValue* value,
+ Handle<Map> map,
+ Handle<AccessorPair> accessors,
+ Handle<JSObject> holder);
+ HInstruction* BuildStoreNamedMonomorphic(HValue* object,
+ Handle<String> name,
+ HValue* value,
+ Handle<Map> map);
HInstruction* BuildStoreKeyedGeneric(HValue* object,
HValue* key,
HValue* value);