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

Unified Diff: src/compiler/ast-graph-builder.cc

Issue 1160983004: [turbofan] First step towards sanitizing for-in and making it optimizable. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add some comments. Created 5 years, 7 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/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
index fb848c9142f31ace157cb93f0860f7fdf95fd1ad..78a0906780e9a6df95e2a808529a7b60078786b4 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -1292,148 +1292,80 @@ void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
}
-// TODO(dcarney): this is a big function. Try to clean up some.
void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
VisitForValue(stmt->subject());
- Node* obj = environment()->Pop();
- // Check for undefined or null before entering loop.
- IfBuilder is_undefined(this);
- Node* is_undefined_cond =
- NewNode(javascript()->StrictEqual(), obj, jsgraph()->UndefinedConstant());
- is_undefined.If(is_undefined_cond);
- is_undefined.Then();
- is_undefined.Else();
+ Node* object = environment()->Pop();
+ BlockBuilder for_block(this);
+ for_block.BeginBlock();
+ // Check for null or undefined before entering loop.
+ Node* is_null_cond =
+ NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
+ for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
+ Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
+ jsgraph()->UndefinedConstant());
+ for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
{
- IfBuilder is_null(this);
- Node* is_null_cond =
- NewNode(javascript()->StrictEqual(), obj, jsgraph()->NullConstant());
- is_null.If(is_null_cond);
- is_null.Then();
- is_null.Else();
// Convert object to jsobject.
- // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
- obj = NewNode(javascript()->ToObject(), obj);
- PrepareFrameState(obj, stmt->ToObjectId(), OutputFrameStateCombine::Push());
- environment()->Push(obj);
- // TODO(dcarney): should do a fast enum cache check here to skip runtime.
- Node* cache_type = NewNode(
- javascript()->CallRuntime(Runtime::kGetPropertyNamesFast, 1), obj);
- PrepareFrameState(cache_type, stmt->EnumId(),
- OutputFrameStateCombine::Push());
- // TODO(dcarney): these next runtime calls should be removed in favour of
- // a few simplified instructions.
- Node* cache_pair = NewNode(
- javascript()->CallRuntime(Runtime::kForInInit, 2), obj, cache_type);
- // cache_type may have been replaced.
- Node* cache_array = NewNode(common()->Projection(0), cache_pair);
- cache_type = NewNode(common()->Projection(1), cache_pair);
- Node* cache_length =
- NewNode(javascript()->CallRuntime(Runtime::kForInCacheArrayLength, 2),
- cache_type, cache_array);
+ object = BuildToObject(object, stmt->ToObjectId());
+ environment()->Push(object);
+
+ // Prepare for-in cache.
+ Node* prepare = NewNode(javascript()->ForInPrepare(), object);
+ PrepareFrameState(prepare, stmt->EnumId(), OutputFrameStateCombine::Push());
+ Node* cache_type = NewNode(common()->Projection(0), prepare);
+ Node* cache_array = NewNode(common()->Projection(1), prepare);
+ Node* cache_length = NewNode(common()->Projection(2), prepare);
+
+ // Construct the rest of the environment.
+ environment()->Push(cache_type);
+ environment()->Push(cache_array);
+ environment()->Push(cache_length);
+ environment()->Push(jsgraph()->ZeroConstant());
+
+ // Build the actual loop body.
+ LoopBuilder for_loop(this);
+ for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
{
- // Construct the rest of the environment.
- environment()->Push(cache_type);
- environment()->Push(cache_array);
- environment()->Push(cache_length);
- environment()->Push(jsgraph()->ZeroConstant());
-
- // Build the actual loop body.
- VisitForInBody(stmt);
- }
- is_null.End();
- }
- is_undefined.End();
-}
-
-
-// TODO(dcarney): this is a big function. Try to clean up some.
-void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) {
- LoopBuilder for_loop(this);
- for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
-
- // These stack values are renamed in the case of OSR, so reload them
- // from the environment.
- Node* index = environment()->Peek(0);
- Node* cache_length = environment()->Peek(1);
- Node* cache_array = environment()->Peek(2);
- Node* cache_type = environment()->Peek(3);
- Node* obj = environment()->Peek(4);
-
- // Check loop termination condition (cannot deoptimize).
- {
- FrameStateBeforeAndAfter states(this, BailoutId::None());
- Node* exit_cond = NewNode(javascript()->LessThan(LanguageMode::SLOPPY),
- index, cache_length);
- states.AddToNode(exit_cond, BailoutId::None(),
- OutputFrameStateCombine::Ignore());
- for_loop.BreakUnless(exit_cond);
- }
- Node* pair = NewNode(javascript()->CallRuntime(Runtime::kForInNext, 4), obj,
- cache_array, cache_type, index);
- Node* value = NewNode(common()->Projection(0), pair);
- Node* should_filter = NewNode(common()->Projection(1), pair);
- environment()->Push(value);
- {
- // Test if FILTER_KEY needs to be called.
- IfBuilder test_should_filter(this);
- Node* should_filter_cond = NewNode(
- javascript()->StrictEqual(), should_filter, jsgraph()->TrueConstant());
- test_should_filter.If(should_filter_cond);
- test_should_filter.Then();
- value = environment()->Pop();
- Node* builtins = BuildLoadBuiltinsObject();
- Node* function = BuildLoadObjectField(
- builtins,
- JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY));
- // result is either the string key or Smi(0) indicating the property
- // is gone.
- Node* res = NewNode(
- javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode()),
- function, obj, value);
- PrepareFrameState(res, stmt->FilterId(), OutputFrameStateCombine::Push());
- Node* property_missing =
- NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant());
- {
- IfBuilder is_property_missing(this);
- is_property_missing.If(property_missing);
- is_property_missing.Then();
- // Inc counter and continue (cannot deoptimize).
+ // These stack values are renamed in the case of OSR, so reload them
+ // from the environment.
+ Node* index = environment()->Peek(0);
+ Node* cache_length = environment()->Peek(1);
+ Node* cache_array = environment()->Peek(2);
+ Node* cache_type = environment()->Peek(3);
+ Node* object = environment()->Peek(4);
+
+ // Check loop termination condition.
+ Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
+ for_loop.BreakWhen(exit_cond);
+
+ // Compute the next enumerated value.
+ Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
+ cache_type, index);
+ PrepareFrameState(value, stmt->FilterId(),
+ OutputFrameStateCombine::Push());
+ IfBuilder test_value(this);
+ Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
+ jsgraph()->UndefinedConstant());
+ test_value.If(test_value_cond, BranchHint::kFalse);
+ test_value.Then();
+ test_value.Else();
{
- FrameStateBeforeAndAfter states(this, BailoutId::None());
- Node* index_inc = NewNode(javascript()->Add(LanguageMode::SLOPPY),
- index, jsgraph()->OneConstant());
- states.AddToNode(index_inc, BailoutId::None(),
- OutputFrameStateCombine::Ignore());
- environment()->Poke(0, index_inc);
+ // Bind value and do loop body.
+ VisitForInAssignment(stmt->each(), value, stmt->AssignmentId());
+ VisitIterationBody(stmt, &for_loop);
}
- for_loop.Continue();
- is_property_missing.Else();
- is_property_missing.End();
- }
- // Replace 'value' in environment.
- environment()->Push(res);
- test_should_filter.Else();
- test_should_filter.End();
- }
- value = environment()->Pop();
- // Bind value and do loop body.
- VisitForInAssignment(stmt->each(), value, stmt->AssignmentId());
- VisitIterationBody(stmt, &for_loop);
- index = environment()->Peek(0);
- for_loop.EndBody();
+ test_value.End();
+ index = environment()->Peek(0);
+ for_loop.EndBody();
- // Inc counter and continue (cannot deoptimize).
- {
- FrameStateBeforeAndAfter states(this, BailoutId::None());
- Node* index_inc = NewNode(javascript()->Add(LanguageMode::SLOPPY), index,
- jsgraph()->OneConstant());
- states.AddToNode(index_inc, BailoutId::None(),
- OutputFrameStateCombine::Ignore());
- environment()->Poke(0, index_inc);
+ // Increment counter and continue.
+ index = NewNode(javascript()->ForInStep(), index);
+ environment()->Poke(0, index);
+ }
+ for_loop.EndLoop();
+ environment()->Drop(5);
}
- for_loop.EndLoop();
- environment()->Drop(5);
- // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+ for_block.EndBlock();
}
@@ -3339,6 +3271,13 @@ Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
}
+Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
+ Node* object = NewNode(javascript()->ToObject(), input);
+ PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
+ return object;
+}
+
+
Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
Expression* expr) {
if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698