Cleaned up Hydrogen function signatures related to property access.

This is a refactoring-only CL and the first one in a series for enabling
inlining of accessors. The naming and argument order has been unified a bit, and
some tests have been pushed to the caller in order to get a simpler
signature. Note that the latter temporarily introduces some code redundancy, but
this will be cleaned up in one of the next CLs.

Review URL: https://chromiumcodereview.appspot.com/10826028

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12198 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
svenpanne@chromium.org 2012-07-26 08:55:22 +00:00
parent d37695e30e
commit 0f800eef8e
2 changed files with 92 additions and 92 deletions

View File

@ -4764,11 +4764,12 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
property->RecordTypeFeedback(oracle()); property->RecordTypeFeedback(oracle());
CHECK_ALIVE(VisitForValue(value)); CHECK_ALIVE(VisitForValue(value));
HValue* value = Pop(); HValue* value = Pop();
Handle<String> name = property->key()->AsPropertyName();
HInstruction* store; HInstruction* store;
CHECK_ALIVE(store = BuildStoreNamed(literal, CHECK_ALIVE(store = BuildStoreNamed(literal,
name,
value, value,
property->GetReceiverType(), property->GetReceiverType()));
property->key()));
AddInstruction(store); AddInstruction(store);
if (store->HasObservableSideEffects()) AddSimulate(key->id()); if (store->HasObservableSideEffects()) AddSimulate(key->id());
} else { } else {
@ -4939,20 +4940,20 @@ static int ComputeLoadStoreFieldIndex(Handle<Map> type,
HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
Handle<String> name, Handle<String> name,
HValue* value, HValue* value,
Handle<Map> type, Handle<Map> map,
LookupResult* lookup, LookupResult* lookup,
bool smi_and_map_check) { bool smi_and_map_check) {
ASSERT(lookup->IsFound()); ASSERT(lookup->IsFound());
if (smi_and_map_check) { if (smi_and_map_check) {
AddInstruction(new(zone()) HCheckNonSmi(object)); AddInstruction(new(zone()) HCheckNonSmi(object));
AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone()));
} }
// If the property does not exist yet, we have to check that it wasn't made // If the property does not exist yet, we have to check that it wasn't made
// readonly or turned into a setter by some meanwhile modifications on the // readonly or turned into a setter by some meanwhile modifications on the
// prototype chain. // prototype chain.
if (!lookup->IsProperty() && type->prototype()->IsJSReceiver()) { if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) {
Object* proto = type->prototype(); Object* proto = map->prototype();
// First check that the prototype chain isn't affected already. // First check that the prototype chain isn't affected already.
LookupResult proto_result(isolate()); LookupResult proto_result(isolate());
proto->Lookup(*name, &proto_result); proto->Lookup(*name, &proto_result);
@ -4971,24 +4972,24 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
} }
ASSERT(proto->IsJSObject()); ASSERT(proto->IsJSObject());
AddInstruction(new(zone()) HCheckPrototypeMaps( AddInstruction(new(zone()) HCheckPrototypeMaps(
Handle<JSObject>(JSObject::cast(type->prototype())), Handle<JSObject>(JSObject::cast(map->prototype())),
Handle<JSObject>(JSObject::cast(proto)))); Handle<JSObject>(JSObject::cast(proto))));
} }
int index = ComputeLoadStoreFieldIndex(type, name, lookup); int index = ComputeLoadStoreFieldIndex(map, name, lookup);
bool is_in_object = index < 0; bool is_in_object = index < 0;
int offset = index * kPointerSize; int offset = index * kPointerSize;
if (index < 0) { if (index < 0) {
// Negative property indices are in-object properties, indexed // Negative property indices are in-object properties, indexed
// from the end of the fixed part of the object. // from the end of the fixed part of the object.
offset += type->instance_size(); offset += map->instance_size();
} else { } else {
offset += FixedArray::kHeaderSize; offset += FixedArray::kHeaderSize;
} }
HStoreNamedField* instr = HStoreNamedField* instr =
new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); new(zone()) HStoreNamedField(object, name, value, is_in_object, offset);
if (lookup->IsTransitionToField(*type)) { if (lookup->IsTransitionToField(*map)) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
instr->set_transition(transition); instr->set_transition(transition);
// TODO(fschneider): Record the new map type of the object in the IR to // TODO(fschneider): Record the new map type of the object in the IR to
// enable elimination of redundant checks after the transition store. // enable elimination of redundant checks after the transition store.
@ -5025,53 +5026,55 @@ static void LookupInPrototypes(Handle<Map> map,
} }
HInstruction* HGraphBuilder::BuildCallSetter(HValue* obj, HInstruction* HGraphBuilder::BuildCallSetter(HValue* object,
Handle<String> name,
HValue* value, HValue* value,
Handle<Map> map, Handle<Map> map,
Handle<Object> callback, Handle<AccessorPair> accessors,
Handle<JSObject> holder) { Handle<JSObject> holder) {
if (!callback->IsAccessorPair()) { Handle<JSFunction> setter(JSFunction::cast(accessors->setter()));
return BuildStoreNamedGeneric(obj, name, value); AddCheckConstantFunction(holder, object, map, true);
} AddInstruction(new(zone()) HPushArgument(object));
Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
Handle<JSFunction> function(Handle<JSFunction>::cast(setter));
AddCheckConstantFunction(holder, obj, map, true);
AddInstruction(new(zone()) HPushArgument(obj));
AddInstruction(new(zone()) HPushArgument(value)); AddInstruction(new(zone()) HPushArgument(value));
return new(zone()) HCallConstantFunction(function, 2); return new(zone()) HCallConstantFunction(setter, 2);
} }
HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
Handle<String> name,
HValue* value, HValue* value,
Handle<Map> type, Handle<Map> map) {
Expression* key) {
// If we don't know the monomorphic type, do a generic store. // If we don't know the monomorphic type, do a generic store.
Handle<String> name = Handle<String>::cast(key->AsLiteral()->handle()); if (map.is_null()) return BuildStoreNamedGeneric(object, name, value);
if (type.is_null()) return BuildStoreNamedGeneric(object, name, value);
// Handle a store to a known field. // Handle a store to a known field.
LookupResult lookup(isolate()); LookupResult lookup(isolate());
if (ComputeLoadStoreField(type, name, &lookup, true)) { if (ComputeLoadStoreField(map, name, &lookup, true)) {
// true = needs smi and map check. // true = needs smi and map check.
return BuildStoreNamedField(object, name, value, type, &lookup, true); return BuildStoreNamedField(object, name, value, map, &lookup, true);
} }
// Handle a known setter directly in the receiver. // Handle a known setter directly in the receiver.
type->LookupDescriptor(NULL, *name, &lookup); map->LookupDescriptor(NULL, *name, &lookup);
if (lookup.IsPropertyCallbacks()) { if (lookup.IsPropertyCallbacks()) {
Handle<Object> callback(lookup.GetValueFromMap(*type)); Handle<Object> callback(lookup.GetValueFromMap(*map));
Handle<JSObject> holder; Handle<JSObject> holder;
return BuildCallSetter(object, name, value, type, callback, 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. // Handle a known setter somewhere in the prototype chain.
LookupInPrototypes(type, name, &lookup); LookupInPrototypes(map, name, &lookup);
if (lookup.IsPropertyCallbacks()) { if (lookup.IsPropertyCallbacks()) {
Handle<Object> callback(lookup.GetValue()); Handle<Object> callback(lookup.GetValue());
Handle<JSObject> holder(lookup.holder()); Handle<JSObject> holder(lookup.holder());
return BuildCallSetter(object, name, value, type, callback, 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. // No luck, do a generic store.
@ -5118,7 +5121,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
HInstruction* instr; HInstruction* instr;
if (count == types->length() && is_monomorphic_field) { if (count == types->length() && is_monomorphic_field) {
AddInstruction(new(zone()) HCheckMaps(object, types, zone())); AddInstruction(new(zone()) HCheckMaps(object, types, zone()));
instr = BuildLoadNamedField(object, expr, map, &lookup, false); instr = BuildLoadNamedField(object, map, &lookup, false);
} else { } else {
HValue* context = environment()->LookupContext(); HValue* context = environment()->LookupContext();
instr = new(zone()) HLoadNamedFieldPolymorphic(context, instr = new(zone()) HLoadNamedFieldPolymorphic(context,
@ -5231,9 +5234,9 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
SmallMapList* types = expr->GetReceiverTypes(); SmallMapList* types = expr->GetReceiverTypes();
if (expr->IsMonomorphic()) { if (expr->IsMonomorphic()) {
CHECK_ALIVE(instr = BuildStoreNamed(object, CHECK_ALIVE(instr = BuildStoreNamed(object,
name,
value, value,
types->first(), types->first()));
prop->key()));
} else if (types != NULL && types->length() > 1) { } else if (types != NULL && types->length() > 1) {
HandlePolymorphicStoreNamedField(expr, object, value, types, name); HandlePolymorphicStoreNamedField(expr, object, value, types, name);
@ -5391,16 +5394,16 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
if (prop->key()->IsPropertyName()) { if (prop->key()->IsPropertyName()) {
// Named property. // Named property.
CHECK_ALIVE(VisitForValue(prop->obj())); CHECK_ALIVE(VisitForValue(prop->obj()));
HValue* obj = Top(); HValue* object = Top();
Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
Handle<Map> map; Handle<Map> map;
HInstruction* load; HInstruction* load;
if (prop->IsMonomorphic()) { if (prop->IsMonomorphic()) {
Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
map = prop->GetReceiverTypes()->first(); map = prop->GetReceiverTypes()->first();
load = BuildLoadNamed(obj, prop, map, name); load = BuildLoadNamed(object, name, prop, map);
} else { } else {
load = BuildLoadNamedGeneric(obj, prop); load = BuildLoadNamedGeneric(object, name, prop);
} }
PushAndAdd(load); PushAndAdd(load);
if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId());
@ -5414,7 +5417,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); if (instr->HasObservableSideEffects()) AddSimulate(operation->id());
HInstruction* store; HInstruction* store;
CHECK_ALIVE(store = BuildStoreNamed(obj, instr, map, prop->key())); CHECK_ALIVE(store = BuildStoreNamed(object, name, instr, map));
AddInstruction(store); AddInstruction(store);
// Drop the simulated receiver and value. Return the value. // Drop the simulated receiver and value. Return the value.
Drop(2); Drop(2);
@ -5615,20 +5618,19 @@ void HGraphBuilder::VisitThrow(Throw* expr) {
HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
Property* expr, Handle<Map> map,
Handle<Map> type,
LookupResult* lookup, LookupResult* lookup,
bool smi_and_map_check) { bool smi_and_map_check) {
if (smi_and_map_check) { if (smi_and_map_check) {
AddInstruction(new(zone()) HCheckNonSmi(object)); AddInstruction(new(zone()) HCheckNonSmi(object));
AddInstruction(HCheckMaps::NewWithTransitions(object, type, zone())); AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone()));
} }
int index = lookup->GetLocalFieldIndexFromMap(*type); int index = lookup->GetLocalFieldIndexFromMap(*map);
if (index < 0) { if (index < 0) {
// Negative property indices are in-object properties, indexed // Negative property indices are in-object properties, indexed
// from the end of the fixed part of the object. // from the end of the fixed part of the object.
int offset = (index * kPointerSize) + type->instance_size(); int offset = (index * kPointerSize) + map->instance_size();
return new(zone()) HLoadNamedField(object, true, offset); return new(zone()) HLoadNamedField(object, true, offset);
} else { } else {
// Non-negative property indices are in the properties array. // Non-negative property indices are in the properties array.
@ -5639,61 +5641,61 @@ HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
Handle<String> name,
Property* expr) { Property* expr) {
if (expr->IsUninitialized() && !FLAG_always_opt) { if (expr->IsUninitialized() && !FLAG_always_opt) {
AddInstruction(new(zone()) HSoftDeoptimize); AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing(); current_block()->MarkAsDeoptimizing();
} }
ASSERT(expr->key()->IsPropertyName());
Handle<Object> name = expr->key()->AsLiteral()->handle();
HValue* context = environment()->LookupContext(); HValue* context = environment()->LookupContext();
return new(zone()) HLoadNamedGeneric(context, obj, name); return new(zone()) HLoadNamedGeneric(context, obj, name);
} }
HInstruction* HGraphBuilder::BuildCallGetter(HValue* obj, HInstruction* HGraphBuilder::BuildCallGetter(HValue* object,
Property* expr,
Handle<Map> map, Handle<Map> map,
Handle<Object> callback, Handle<AccessorPair> accessors,
Handle<JSObject> holder) { Handle<JSObject> holder) {
if (!callback->IsAccessorPair()) return BuildLoadNamedGeneric(obj, expr); Handle<JSFunction> getter(JSFunction::cast(accessors->getter()));
Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter()); AddCheckConstantFunction(holder, object, map, true);
Handle<JSFunction> function(Handle<JSFunction>::cast(getter)); AddInstruction(new(zone()) HPushArgument(object));
AddCheckConstantFunction(holder, obj, map, true); return new(zone()) HCallConstantFunction(getter, 1);
AddInstruction(new(zone()) HPushArgument(obj));
return new(zone()) HCallConstantFunction(function, 1);
} }
HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, HInstruction* HGraphBuilder::BuildLoadNamed(HValue* object,
Handle<String> name,
Property* expr, Property* expr,
Handle<Map> map, Handle<Map> map) {
Handle<String> name) {
LookupResult lookup(isolate()); LookupResult lookup(isolate());
map->LookupDescriptor(NULL, *name, &lookup); map->LookupDescriptor(NULL, *name, &lookup);
if (lookup.IsField()) { if (lookup.IsField()) {
return BuildLoadNamedField(obj, return BuildLoadNamedField(object, map, &lookup, true);
expr,
map,
&lookup,
true);
} else if (lookup.IsConstantFunction()) { } else if (lookup.IsConstantFunction()) {
AddInstruction(new(zone()) HCheckNonSmi(obj)); AddInstruction(new(zone()) HCheckNonSmi(object));
AddInstruction(HCheckMaps::NewWithTransitions(obj, map, zone())); AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone()));
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
return new(zone()) HConstant(function, Representation::Tagged()); return new(zone()) HConstant(function, Representation::Tagged());
} else if (lookup.IsPropertyCallbacks()) { } else if (lookup.IsPropertyCallbacks()) {
Handle<Object> callback(lookup.GetValueFromMap(*map)); Handle<Object> callback(lookup.GetValueFromMap(*map));
Handle<JSObject> holder; Handle<JSObject> holder;
return BuildCallGetter(obj, expr, map, callback, holder); if (!callback->IsAccessorPair()) {
return BuildLoadNamedGeneric(object, name, expr);
}
Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback);
return BuildCallGetter(object, map, accessors, holder);
} else { } else {
LookupInPrototypes(map, name, &lookup); LookupInPrototypes(map, name, &lookup);
if (lookup.IsPropertyCallbacks()) { if (lookup.IsPropertyCallbacks()) {
Handle<Object> callback(lookup.GetValue()); Handle<Object> callback(lookup.GetValue());
Handle<JSObject> holder(lookup.holder()); Handle<JSObject> holder(lookup.holder());
return BuildCallGetter(obj, expr, map, callback, holder); if (!callback->IsAccessorPair()) {
return BuildLoadNamedGeneric(object, name, expr);
}
Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(callback);
return BuildCallGetter(object, map, accessors, holder);
} }
return BuildLoadNamedGeneric(obj, expr); return BuildLoadNamedGeneric(object, name, expr);
} }
} }
@ -6313,13 +6315,13 @@ void HGraphBuilder::VisitProperty(Property* expr) {
HValue* obj = Pop(); HValue* obj = Pop();
if (expr->IsMonomorphic()) { if (expr->IsMonomorphic()) {
instr = BuildLoadNamed(obj, expr, types->first(), name); instr = BuildLoadNamed(obj, name, expr, types->first());
} else if (types != NULL && types->length() > 1) { } else if (types != NULL && types->length() > 1) {
AddInstruction(new(zone()) HCheckNonSmi(obj)); AddInstruction(new(zone()) HCheckNonSmi(obj));
HandlePolymorphicLoadNamedField(expr, obj, types, name); HandlePolymorphicLoadNamedField(expr, obj, types, name);
return; return;
} else { } else {
instr = BuildLoadNamedGeneric(obj, expr); instr = BuildLoadNamedGeneric(obj, name, expr);
} }
} else { } else {
@ -7798,14 +7800,14 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
CHECK_ALIVE(VisitForValue(prop->obj())); CHECK_ALIVE(VisitForValue(prop->obj()));
HValue* obj = Top(); HValue* obj = Top();
Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
Handle<Map> map; Handle<Map> map;
HInstruction* load; HInstruction* load;
if (prop->IsMonomorphic()) { if (prop->IsMonomorphic()) {
Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
map = prop->GetReceiverTypes()->first(); map = prop->GetReceiverTypes()->first();
load = BuildLoadNamed(obj, prop, map, name); load = BuildLoadNamed(obj, name, prop, map);
} else { } else {
load = BuildLoadNamedGeneric(obj, prop); load = BuildLoadNamedGeneric(obj, name, prop);
} }
PushAndAdd(load); PushAndAdd(load);
if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); if (load->HasObservableSideEffects()) AddSimulate(expr->CountId());
@ -7814,7 +7816,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
input = Pop(); input = Pop();
HInstruction* store; HInstruction* store;
CHECK_ALIVE(store = BuildStoreNamed(obj, after, map, prop->key())); CHECK_ALIVE(store = BuildStoreNamed(obj, name, after, map));
AddInstruction(store); AddInstruction(store);
// Overwrite the receiver in the bailout environment with the result // Overwrite the receiver in the bailout environment with the result

View File

@ -1089,13 +1089,13 @@ class HGraphBuilder: public AstVisitor {
HInstruction* BuildIncrement(bool returns_original_input, HInstruction* BuildIncrement(bool returns_original_input,
CountOperation* expr); CountOperation* expr);
HLoadNamedField* BuildLoadNamedField(HValue* object, HLoadNamedField* BuildLoadNamedField(HValue* object,
Property* expr, Handle<Map> map,
Handle<Map> type,
LookupResult* result, LookupResult* result,
bool smi_and_map_check); bool smi_and_map_check);
HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr); HInstruction* BuildLoadNamedGeneric(HValue* object,
HInstruction* BuildLoadKeyedGeneric(HValue* object, Handle<String> name,
HValue* key); Property* expr);
HInstruction* BuildLoadKeyedGeneric(HValue* object, HValue* key);
HInstruction* BuildExternalArrayElementAccess( HInstruction* BuildExternalArrayElementAccess(
HValue* external_elements, HValue* external_elements,
HValue* checked_key, HValue* checked_key,
@ -1147,29 +1147,27 @@ class HGraphBuilder: public AstVisitor {
bool is_store, bool is_store,
bool* has_side_effects); bool* has_side_effects);
HInstruction* BuildCallGetter(HValue* obj, HInstruction* BuildCallGetter(HValue* object,
Property* expr,
Handle<Map> map, Handle<Map> map,
Handle<Object> callback, Handle<AccessorPair> accessors,
Handle<JSObject> holder); Handle<JSObject> holder);
HInstruction* BuildLoadNamed(HValue* object, HInstruction* BuildLoadNamed(HValue* object,
Property* prop, Handle<String> name,
Handle<Map> map, Property* expr,
Handle<String> name); Handle<Map> map);
HInstruction* BuildCallSetter(HValue* object, HInstruction* BuildCallSetter(HValue* object,
Handle<String> name,
HValue* value, HValue* value,
Handle<Map> map, Handle<Map> map,
Handle<Object> callback, Handle<AccessorPair> accessors,
Handle<JSObject> holder); Handle<JSObject> holder);
HInstruction* BuildStoreNamed(HValue* object, HInstruction* BuildStoreNamed(HValue* object,
Handle<String> name,
HValue* value, HValue* value,
Handle<Map> type, Handle<Map> map);
Expression* key);
HInstruction* BuildStoreNamedField(HValue* object, HInstruction* BuildStoreNamedField(HValue* object,
Handle<String> name, Handle<String> name,
HValue* value, HValue* value,
Handle<Map> type, Handle<Map> map,
LookupResult* lookup, LookupResult* lookup,
bool smi_and_map_check); bool smi_and_map_check);
HInstruction* BuildStoreNamedGeneric(HValue* object, HInstruction* BuildStoreNamedGeneric(HValue* object,