| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index e7fbabae1d51e489709c29a9e13f03f51dcd9024..2ab52b778d47409081cdea1ff271cb4b92b4cf33 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -3794,6 +3794,13 @@ void TestContext::BuildBranch(HValue* value) {
|
| } while (false)
|
|
|
|
|
| +#define CHECK_ALIVE_OR_RETURN(call, value) \
|
| + do { \
|
| + call; \
|
| + if (HasStackOverflow() || current_block() == NULL) return value; \
|
| + } while (false)
|
| +
|
| +
|
| void HOptimizedGraphBuilder::Bailout(const char* reason) {
|
| current_info()->set_bailout_reason(reason);
|
| SetStackOverflow();
|
| @@ -6296,13 +6303,13 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
|
| Handle<String> name) {
|
| // Use monomorphic load if property lookup results in the same field index
|
| // for all maps. Requires special map check on the set of all handled maps.
|
| + if (types->length() > kMaxLoadPolymorphism) return NULL;
|
| +
|
| LookupResult lookup(isolate());
|
| int count;
|
| Representation representation = Representation::None();
|
| HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
|
| - for (count = 0;
|
| - count < types->length() && count < kMaxLoadPolymorphism;
|
| - ++count) {
|
| + for (count = 0; count < types->length(); ++count) {
|
| Handle<Map> map = types->at(count);
|
| if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
|
|
|
| @@ -6313,7 +6320,6 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
|
| if (count == 0) {
|
| // First time through the loop; set access and representation.
|
| access = new_access;
|
| - representation = new_representation;
|
| } else if (!representation.IsCompatibleForLoad(new_representation)) {
|
| // Representations did not match.
|
| break;
|
| @@ -6324,6 +6330,7 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
|
| // In-objectness did not match.
|
| break;
|
| }
|
| + representation = representation.generalize(new_representation);
|
| }
|
|
|
| if (count != types->length()) return NULL;
|
| @@ -6355,12 +6362,75 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
|
| }
|
|
|
|
|
| +bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
|
| + Assignment* expr,
|
| + HValue* object,
|
| + HValue* value,
|
| + SmallMapList* types,
|
| + Handle<String> name) {
|
| + // Use monomorphic store if property lookup results in the same field index
|
| + // for all maps. Requires special map check on the set of all handled maps.
|
| + if (types->length() > kMaxStorePolymorphism) return false;
|
| +
|
| + // TODO(verwaest): Merge the checking logic with the code in
|
| + // TryLoadPolymorphicAsMonomorphic.
|
| + LookupResult lookup(isolate());
|
| + int count;
|
| + Representation representation = Representation::None();
|
| + HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
|
| + for (count = 0; count < types->length(); ++count) {
|
| + Handle<Map> map = types->at(count);
|
| + // Pass false to ignore transitions.
|
| + if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
|
| +
|
| + HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
|
| + Representation new_representation =
|
| + ComputeLoadStoreRepresentation(map, &lookup);
|
| +
|
| + if (count == 0) {
|
| + // First time through the loop; set access and representation.
|
| + access = new_access;
|
| + representation = new_representation;
|
| + } else if (!representation.IsCompatibleForStore(new_representation)) {
|
| + // Representations did not match.
|
| + break;
|
| + } else if (access.offset() != new_access.offset()) {
|
| + // Offsets did not match.
|
| + break;
|
| + } else if (access.IsInobject() != new_access.IsInobject()) {
|
| + // In-objectness did not match.
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (count != types->length()) return false;
|
| +
|
| + // Everything matched; can use monomorphic store.
|
| + BuildCheckNonSmi(object);
|
| + AddInstruction(HCheckMaps::New(object, types, zone()));
|
| + HInstruction* store;
|
| + CHECK_ALIVE_OR_RETURN(
|
| + store = BuildStoreNamedField(object, name, value, types->at(0), &lookup),
|
| + true);
|
| + Push(value);
|
| + store->set_position(expr->position());
|
| + AddInstruction(store);
|
| + AddSimulate(expr->AssignmentId());
|
| + ast_context()->ReturnValue(Pop());
|
| + return true;
|
| +}
|
| +
|
| +
|
| void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
| Assignment* expr,
|
| HValue* object,
|
| HValue* value,
|
| SmallMapList* types,
|
| Handle<String> name) {
|
| + if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) {
|
| + return;
|
| + }
|
| +
|
| // 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.
|
| @@ -6383,8 +6453,8 @@ 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, value, map, &lookup));
|
| instr->set_position(expr->position());
|
| // Goto will add the HSimulate for the store.
|
| AddInstruction(instr);
|
| @@ -6428,7 +6498,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
|
| ASSERT(join != NULL);
|
| join->SetJoinId(expr->id());
|
| set_current_block(join);
|
| - if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
|
| + if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
|
| }
|
|
|
|
|
|
|