| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 54e44c077011845addf101f2726818ec2b06316f..1091622ea2802586a6d1a126c3c148e359f22979 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -4662,6 +4662,86 @@ void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| }
|
|
|
|
|
| +static void LookupInPrototypes(Handle<Map> map,
|
| + Handle<String> name,
|
| + LookupResult* lookup) {
|
| + while (map->prototype()->IsJSObject()) {
|
| + Handle<JSObject> holder(JSObject::cast(map->prototype()));
|
| + if (!holder->HasFastProperties()) break;
|
| + map = Handle<Map>(holder->map());
|
| + map->LookupDescriptor(*holder, *name, lookup);
|
| + if (lookup->IsFound()) return;
|
| + }
|
| + lookup->NotFound();
|
| +}
|
| +
|
| +
|
| +// 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).
|
| +static bool LookupAccessorPair(Handle<Map> map,
|
| + Handle<String> name,
|
| + Handle<AccessorPair>* accessors,
|
| + Handle<JSObject>* holder) {
|
| + LookupResult lookup(map->GetIsolate());
|
| +
|
| + // 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;
|
| +}
|
| +
|
| +
|
| +static bool LookupGetter(Handle<Map> map,
|
| + Handle<String> name,
|
| + Handle<JSFunction>* getter,
|
| + Handle<JSObject>* holder) {
|
| + Handle<AccessorPair> accessors;
|
| + if (LookupAccessorPair(map, name, &accessors, holder) &&
|
| + accessors->getter()->IsJSFunction()) {
|
| + *getter = Handle<JSFunction>(JSFunction::cast(accessors->getter()));
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| +static bool LookupSetter(Handle<Map> map,
|
| + Handle<String> name,
|
| + Handle<JSFunction>* setter,
|
| + Handle<JSObject>* holder) {
|
| + Handle<AccessorPair> accessors;
|
| + if (LookupAccessorPair(map, name, &accessors, holder) &&
|
| + accessors->setter()->IsJSFunction()) {
|
| + *setter = Handle<JSFunction>(JSFunction::cast(accessors->setter()));
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| // Determines whether the given array or object literal boilerplate satisfies
|
| // all limits to be considered for fast deep-copying and computes the total
|
| // size of all objects that are part of the graph.
|
| @@ -4787,9 +4867,9 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
| CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value));
|
| } else {
|
| #if DEBUG
|
| - Handle<AccessorPair> accessors;
|
| + Handle<JSFunction> setter;
|
| Handle<JSObject> holder;
|
| - ASSERT(!LookupAccessorPair(map, name, &accessors, &holder));
|
| + ASSERT(!LookupSetter(map, name, &setter, &holder));
|
| #endif
|
| CHECK_ALIVE(store = BuildStoreNamedMonomorphic(literal,
|
| name,
|
| @@ -5038,26 +5118,11 @@ HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
|
| }
|
|
|
|
|
| -static void LookupInPrototypes(Handle<Map> map,
|
| - Handle<String> name,
|
| - LookupResult* lookup) {
|
| - while (map->prototype()->IsJSObject()) {
|
| - Handle<JSObject> holder(JSObject::cast(map->prototype()));
|
| - if (!holder->HasFastProperties()) break;
|
| - map = Handle<Map>(holder->map());
|
| - map->LookupDescriptor(*holder, *name, lookup);
|
| - if (lookup->IsFound()) return;
|
| - }
|
| - lookup->NotFound();
|
| -}
|
| -
|
| -
|
| HInstruction* HGraphBuilder::BuildCallSetter(HValue* object,
|
| HValue* value,
|
| Handle<Map> map,
|
| - Handle<AccessorPair> accessors,
|
| + Handle<JSFunction> setter,
|
| Handle<JSObject> holder) {
|
| - Handle<JSFunction> setter(JSFunction::cast(accessors->setter()));
|
| AddCheckConstantFunction(holder, object, map, true);
|
| AddInstruction(new(zone()) HPushArgument(object));
|
| AddInstruction(new(zone()) HPushArgument(value));
|
| @@ -5237,10 +5302,9 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
|
| if (map->is_dictionary_map()) monomorphic = false;
|
| }
|
| if (monomorphic) {
|
| - Handle<AccessorPair> accessors;
|
| + Handle<JSFunction> setter;
|
| Handle<JSObject> holder;
|
| - if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| - Handle<JSFunction> setter(JSFunction::cast(accessors->setter()));
|
| + if (LookupSetter(map, name, &setter, &holder)) {
|
| AddCheckConstantFunction(holder, object, map, true);
|
| if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) {
|
| return;
|
| @@ -5427,10 +5491,10 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
| if (map->is_dictionary_map()) monomorphic = false;
|
| }
|
| if (monomorphic) {
|
| - Handle<AccessorPair> accessors;
|
| + Handle<JSFunction> getter;
|
| Handle<JSObject> holder;
|
| - if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| - load = BuildCallGetter(object, map, accessors, holder);
|
| + if (LookupGetter(map, name, &getter, &holder)) {
|
| + load = BuildCallGetter(object, map, getter, holder);
|
| } else {
|
| load = BuildLoadNamedMonomorphic(object, name, prop, map);
|
| }
|
| @@ -5453,12 +5517,10 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
|
| // If we don't know the monomorphic type, do a generic store.
|
| CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr));
|
| } else {
|
| - Handle<AccessorPair> accessors;
|
| + Handle<JSFunction> setter;
|
| Handle<JSObject> holder;
|
| - // Because we re-use the load type feedback, there might be no setter.
|
| - if (LookupAccessorPair(map, name, &accessors, &holder) &&
|
| - accessors->setter()->IsJSFunction()) {
|
| - store = BuildCallSetter(object, instr, map, accessors, holder);
|
| + if (LookupSetter(map, name, &setter, &holder)) {
|
| + store = BuildCallSetter(object, instr, map, setter, holder);
|
| } else {
|
| CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
|
| name,
|
| @@ -5702,49 +5764,14 @@ HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* object,
|
|
|
| HInstruction* HGraphBuilder::BuildCallGetter(HValue* object,
|
| Handle<Map> map,
|
| - Handle<AccessorPair> accessors,
|
| + Handle<JSFunction> getter,
|
| Handle<JSObject> holder) {
|
| - Handle<JSFunction> getter(JSFunction::cast(accessors->getter()));
|
| AddCheckConstantFunction(holder, object, map, true);
|
| AddInstruction(new(zone()) HPushArgument(object));
|
| return new(zone()) HCallConstantFunction(getter, 1);
|
| }
|
|
|
|
|
| -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,
|
| @@ -6391,11 +6418,10 @@ void HGraphBuilder::VisitProperty(Property* expr) {
|
| if (map->is_dictionary_map()) monomorphic = false;
|
| }
|
| if (monomorphic) {
|
| - Handle<AccessorPair> accessors;
|
| + Handle<JSFunction> getter;
|
| Handle<JSObject> holder;
|
| - if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| + if (LookupGetter(map, name, &getter, &holder)) {
|
| AddCheckConstantFunction(holder, Top(), map, true);
|
| - Handle<JSFunction> getter(JSFunction::cast(accessors->getter()));
|
| if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return;
|
| AddInstruction(new(zone()) HPushArgument(Pop()));
|
| instr = new(zone()) HCallConstantFunction(getter, 1);
|
| @@ -7867,10 +7893,10 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| if (map->is_dictionary_map()) monomorphic = false;
|
| }
|
| if (monomorphic) {
|
| - Handle<AccessorPair> accessors;
|
| + Handle<JSFunction> getter;
|
| Handle<JSObject> holder;
|
| - if (LookupAccessorPair(map, name, &accessors, &holder)) {
|
| - load = BuildCallGetter(object, map, accessors, holder);
|
| + if (LookupGetter(map, name, &getter, &holder)) {
|
| + load = BuildCallGetter(object, map, getter, holder);
|
| } else {
|
| load = BuildLoadNamedMonomorphic(object, name, prop, map);
|
| }
|
| @@ -7888,12 +7914,10 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| // If we don't know the monomorphic type, do a generic store.
|
| CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after));
|
| } else {
|
| - Handle<AccessorPair> accessors;
|
| + Handle<JSFunction> setter;
|
| Handle<JSObject> holder;
|
| - // Because we re-use the load type feedback, there might be no setter.
|
| - if (LookupAccessorPair(map, name, &accessors, &holder) &&
|
| - accessors->setter()->IsJSFunction()) {
|
| - store = BuildCallSetter(object, after, map, accessors, holder);
|
| + if (LookupSetter(map, name, &setter, &holder)) {
|
| + store = BuildCallSetter(object, after, map, setter, holder);
|
| } else {
|
| CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
|
| name,
|
|
|