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

Unified Diff: src/hydrogen.cc

Issue 148883002: Synchronize with r15594. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 5fd55f833cf1965c3ce87fef5c697b5561c1d9f0..ed2dac226fc466146a18f46faeb9de796e698620 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1161,7 +1161,7 @@ HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
BuildNewElementsCapacity(context, current_capacity);
HValue* new_elements = BuildGrowElementsCapacity(object, elements,
- kind, length,
+ kind, kind, length,
new_capacity);
environment()->Push(new_elements);
@@ -1205,7 +1205,7 @@ HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
HValue* capacity = AddLoadFixedArrayLength(elements);
- HValue* new_elements = BuildGrowElementsCapacity(object, elements,
+ HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
kind, length, capacity);
environment()->Push(new_elements);
@@ -1477,17 +1477,18 @@ void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
HValue* elements,
ElementsKind kind,
+ ElementsKind new_kind,
HValue* length,
HValue* new_capacity) {
HValue* context = environment()->LookupContext();
- BuildNewSpaceArrayCheck(new_capacity, kind);
+ BuildNewSpaceArrayCheck(new_capacity, new_kind);
HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
- context, kind, new_capacity);
+ context, new_kind, new_capacity);
BuildCopyElements(context, elements, kind,
- new_elements, kind,
+ new_elements, new_kind,
length, new_capacity);
AddStore(object, HObjectAccess::ForElementsPointer(), new_elements);
@@ -1959,7 +1960,7 @@ HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin,
- HContext* context) {
+ HValue* context) {
HGlobalObject* global_object = Add<HGlobalObject>(context);
HObjectAccess access = HObjectAccess::ForJSObjectOffset(
GlobalObject::kBuiltinsOffset);
@@ -4652,7 +4653,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
}
site = isolate()->factory()->NewAllocationSite();
- site->set_payload(*raw_boilerplate);
+ site->set_transition_info(*raw_boilerplate);
literals->set(expr->literal_index(), *site);
if (JSObject::cast(*raw_boilerplate)->elements()->map() ==
@@ -4662,7 +4663,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
} else {
ASSERT(literals_cell->IsAllocationSite());
site = Handle<AllocationSite>::cast(literals_cell);
- raw_boilerplate = Handle<Object>(site->payload(), isolate());
+ raw_boilerplate = Handle<Object>(site->transition_info(), isolate());
}
ASSERT(!raw_boilerplate.is_null());
@@ -4776,6 +4777,7 @@ static bool ComputeLoadStoreField(Handle<Map> type,
Handle<String> name,
LookupResult* lookup,
bool is_store) {
+ ASSERT(!is_store || !type->is_observed());
if (type->has_named_interceptor()) {
lookup->InterceptorResult(NULL);
return false;
@@ -4943,6 +4945,17 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
}
+static bool CanLoadPropertyFromPrototype(Handle<Map> map,
+ Handle<Name> name,
+ LookupResult* lookup) {
+ if (map->has_named_interceptor()) return false;
+ if (map->is_dictionary_map()) return false;
+ map->LookupDescriptor(NULL, *name, lookup);
+ if (lookup->IsFound()) return false;
+ return true;
+}
+
+
HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
Property* expr,
HValue* object,
@@ -4980,12 +4993,40 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
representation = representation.generalize(new_representation);
}
- if (count != types->length()) return NULL;
+ if (count == types->length()) {
+ // Everything matched; can use monomorphic load.
+ BuildCheckHeapObject(object);
+ AddInstruction(HCheckMaps::New(object, types, zone()));
+ return BuildLoadNamedField(object, access, representation);
+ }
+
+ if (count != 0) return NULL;
+
+ // Second chance: the property is on the prototype and all maps have the
+ // same prototype.
+ Handle<Map> map(types->at(0));
+ if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL;
+
+ Handle<Object> prototype(map->prototype(), isolate());
+ for (count = 1; count < types->length(); ++count) {
+ Handle<Map> test_map(types->at(count));
+ if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL;
+ if (test_map->prototype() != *prototype) return NULL;
+ }
+
+ LookupInPrototypes(map, name, &lookup);
+ if (!lookup.IsField()) return NULL;
- // Everything matched; can use monomorphic load.
BuildCheckHeapObject(object);
AddInstruction(HCheckMaps::New(object, types, zone()));
- return BuildLoadNamedField(object, access, representation);
+ Handle<JSObject> holder(lookup.holder());
+ Handle<Map> holder_map(holder->map());
+ AddInstruction(new(zone()) HCheckPrototypeMaps(
+ Handle<JSObject>::cast(prototype), holder, zone(), top_info()));
+ HValue* holder_value = AddInstruction(new(zone()) HConstant(holder));
+ return BuildLoadNamedField(holder_value,
+ HObjectAccess::ForField(holder_map, &lookup, name),
+ ComputeLoadStoreRepresentation(map, &lookup));
}
@@ -5013,7 +5054,8 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
int position,
BailoutId assignment_id,
HValue* object,
- HValue* value,
+ HValue* store_value,
+ HValue* result_value,
SmallMapList* types,
Handle<String> name) {
// Use monomorphic store if property lookup results in the same field index
@@ -5030,6 +5072,7 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
Handle<Map> map = types->at(count);
// Pass false to ignore transitions.
if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
+ ASSERT(!map->is_observed());
HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
Representation new_representation =
@@ -5059,12 +5102,14 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
HInstruction* store;
CHECK_ALIVE_OR_RETURN(
store = BuildStoreNamedField(
- object, name, value, types->at(count - 1), &lookup),
+ object, name, store_value, types->at(count - 1), &lookup),
true);
- Push(value);
+ if (result_value != NULL) Push(result_value);
+ Push(store_value);
store->set_position(position);
AddInstruction(store);
AddSimulate(assignment_id);
+ if (result_value != NULL) Drop(1);
ast_context()->ReturnValue(Pop());
return true;
}
@@ -5075,11 +5120,13 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
int position,
BailoutId assignment_id,
HValue* object,
- HValue* value,
+ HValue* store_value,
+ HValue* result_value,
SmallMapList* types,
Handle<String> name) {
if (TryStorePolymorphicAsMonomorphic(
- position, assignment_id, object, value, types, name)) {
+ position, assignment_id, object,
+ store_value, result_value, types, name)) {
return;
}
@@ -5105,12 +5152,15 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
set_current_block(if_true);
HInstruction* instr;
- CHECK_ALIVE(
- instr = BuildStoreNamedField(object, name, value, map, &lookup));
+ CHECK_ALIVE(instr = BuildStoreNamedField(
+ object, name, store_value, map, &lookup));
instr->set_position(position);
// Goto will add the HSimulate for the store.
AddInstruction(instr);
- if (!ast_context()->IsEffect()) Push(value);
+ if (!ast_context()->IsEffect()) {
+ if (result_value != NULL) Push(result_value);
+ Push(store_value);
+ }
current_block()->Goto(join);
set_current_block(if_false);
@@ -5123,12 +5173,15 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
} else {
- HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
+ HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value);
instr->set_position(position);
AddInstruction(instr);
if (join != NULL) {
- if (!ast_context()->IsEffect()) Push(value);
+ if (!ast_context()->IsEffect()) {
+ if (result_value != NULL) Push(result_value);
+ Push(store_value);
+ }
current_block()->Goto(join);
} else {
// The HSimulate for the store should not see the stored value in
@@ -5138,19 +5191,24 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
if (ast_context()->IsEffect()) {
AddSimulate(id, REMOVABLE_SIMULATE);
} else {
- Push(value);
+ if (result_value != NULL) Push(result_value);
+ Push(store_value);
AddSimulate(id, REMOVABLE_SIMULATE);
- Drop(1);
+ Drop(result_value != NULL ? 2 : 1);
}
}
- return ast_context()->ReturnValue(value);
+ return ast_context()->ReturnValue(
+ result_value != NULL ? result_value : store_value);
}
}
ASSERT(join != NULL);
join->SetJoinId(id);
set_current_block(join);
- if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
+ if (!ast_context()->IsEffect()) {
+ if (result_value != NULL) Drop(1);
+ ast_context()->ReturnValue(Pop());
+ }
}
@@ -5239,7 +5297,8 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
BailoutId assignment_id,
Property* prop,
HValue* object,
- HValue* value) {
+ HValue* store_value,
+ HValue* result_value) {
Literal* key = prop->key()->AsLiteral();
Handle<String> name = Handle<String>::cast(key->value());
ASSERT(!name.is_null());
@@ -5257,37 +5316,42 @@ void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
Handle<JSObject> holder;
if (LookupSetter(map, name, &setter, &holder)) {
AddCheckConstantFunction(holder, object, map);
- if (FLAG_inline_accessors &&
- TryInlineSetter(setter, id, assignment_id, value)) {
+ // Don't try to inline if the result_value is different from the
+ // store_value. That case isn't handled yet by the inlining.
+ if (result_value == NULL &&
+ FLAG_inline_accessors &&
+ TryInlineSetter(setter, id, assignment_id, store_value)) {
return;
}
Drop(2);
Add<HPushArgument>(object);
- Add<HPushArgument>(value);
+ Add<HPushArgument>(store_value);
instr = new(zone()) HCallConstantFunction(setter, 2);
} else {
Drop(2);
CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
name,
- value,
+ store_value,
map));
}
-
} else if (types != NULL && types->length() > 1) {
Drop(2);
return HandlePolymorphicStoreNamedField(
- id, position, assignment_id, object, value, types, name);
+ id, position, assignment_id, object,
+ store_value, result_value, types, name);
} else {
Drop(2);
- instr = BuildStoreNamedGeneric(object, name, value);
+ instr = BuildStoreNamedGeneric(object, name, store_value);
}
- Push(value);
+ if (result_value != NULL) Push(result_value);
+ Push(store_value);
instr->set_position(position);
AddInstruction(instr);
if (instr->HasObservableSideEffects()) {
AddSimulate(assignment_id, REMOVABLE_SIMULATE);
}
+ if (result_value != NULL) Drop(1);
return ast_context()->ReturnValue(Pop());
}
@@ -6305,14 +6369,60 @@ inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
}
+bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
+ Call* expr,
+ HValue* receiver,
+ SmallMapList* types,
+ Handle<String> name) {
+ if (types->length() > kMaxCallPolymorphism) return false;
+
+ Handle<Map> map(types->at(0));
+ LookupResult lookup(isolate());
+ if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return false;
+
+ Handle<Object> prototype(map->prototype(), isolate());
+ for (int count = 1; count < types->length(); ++count) {
+ Handle<Map> test_map(types->at(count));
+ if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false;
+ if (test_map->prototype() != *prototype) return false;
+ }
+
+ if (!expr->ComputeTarget(map, name)) return false;
+
+ BuildCheckHeapObject(receiver);
+ AddInstruction(HCheckMaps::New(receiver, types, zone()));
+ AddCheckPrototypeMaps(expr->holder(), map);
+ if (FLAG_trace_inlining) {
+ Handle<JSFunction> caller = current_info()->closure();
+ SmartArrayPointer<char> caller_name =
+ caller->shared()->DebugName()->ToCString();
+ PrintF("Trying to inline the polymorphic call to %s from %s\n",
+ *name->ToCString(), *caller_name);
+ }
+
+ if (!TryInlineCall(expr)) {
+ int argument_count = expr->arguments()->length() + 1; // Includes receiver.
+ HCallConstantFunction* call =
+ new(zone()) HCallConstantFunction(expr->target(), argument_count);
+ call->set_position(expr->position());
+ PreProcessCall(call);
+ AddInstruction(call);
+ if (!ast_context()->IsEffect()) Push(call);
+ AddSimulate(expr->id(), REMOVABLE_SIMULATE);
+ if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
+ }
+
+ return true;
+}
+
+
void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
Call* expr,
HValue* receiver,
SmallMapList* types,
Handle<String> name) {
- // TODO(ager): We should recognize when the prototype chains for different
- // maps are identical. In that case we can avoid repeatedly generating the
- // same prototype map checks.
+ if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
+
int argument_count = expr->arguments()->length() + 1; // Includes receiver.
HBasicBlock* join = NULL;
FunctionSorter order[kMaxCallPolymorphism];
@@ -7597,7 +7707,13 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
HValue* key = Pop();
HValue* obj = Pop();
HValue* context = environment()->LookupContext();
- HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
+ HValue* function = AddLoadJSBuiltin(Builtins::DELETE, context);
+ Add<HPushArgument>(obj);
+ Add<HPushArgument>(key);
+ Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag()));
+ // TODO(olivf) InvokeFunction produces a check for the parameter count,
+ // even though we are certain to pass the correct number of arguments here.
+ HInstruction* instr = new(zone()) HInvokeFunction(context, function, 3);
return ast_context()->ReturnInstruction(instr, expr->id());
} else if (proxy != NULL) {
Variable* var = proxy->var();
@@ -7852,35 +7968,11 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
}
after = BuildIncrement(returns_original_input, expr);
- input = Pop();
-
- HInstruction* store;
- if (!monomorphic || map->is_observed()) {
- // If we don't know the monomorphic type, do a generic store.
- CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after));
- } else {
- Handle<JSFunction> setter;
- Handle<JSObject> holder;
- if (LookupSetter(map, name, &setter, &holder)) {
- store = BuildCallSetter(object, after, map, setter, holder);
- } else {
- CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
- name,
- after,
- map));
- }
- }
- AddInstruction(store);
- // Overwrite the receiver in the bailout environment with the result
- // of the operation, and the placeholder with the original value if
- // necessary.
- environment()->SetExpressionStackAt(0, after);
- if (returns_original_input) environment()->SetExpressionStackAt(1, input);
- if (store->HasObservableSideEffects()) {
- AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
- }
+ HValue* result = returns_original_input ? Pop() : NULL;
+ return BuildStoreNamed(prop, expr->id(), expr->position(),
+ expr->AssignmentId(), prop, object, after, result);
} else {
// Keyed property.
if (returns_original_input) Push(graph()->GetConstantUndefined());
@@ -8410,7 +8502,12 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// Code below assumes that we don't fall through.
UNREACHABLE();
} else if (op == Token::IN) {
- HIn* result = new(zone()) HIn(context, left, right);
+ HValue* function = AddLoadJSBuiltin(Builtins::IN, context);
+ Add<HPushArgument>(left);
+ Add<HPushArgument>(right);
+ // TODO(olivf) InvokeFunction produces a check for the parameter count,
+ // even though we are certain to pass the correct number of arguments here.
+ HInstruction* result = new(zone()) HInvokeFunction(context, function, 2);
result->set_position(expr->position());
return ast_context()->ReturnInstruction(result, expr->id());
}
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698