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

Side by Side 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, 6 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/ast-graph-builder.h" 5 #include "src/compiler/ast-graph-builder.h"
6 6
7 #include "src/compiler.h" 7 #include "src/compiler.h"
8 #include "src/compiler/ast-loop-assignment-analyzer.h" 8 #include "src/compiler/ast-loop-assignment-analyzer.h"
9 #include "src/compiler/control-builders.h" 9 #include "src/compiler/control-builders.h"
10 #include "src/compiler/js-type-feedback.h" 10 #include "src/compiler/js-type-feedback.h"
(...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 } else { 1285 } else {
1286 for_loop.BreakUnless(jsgraph()->TrueConstant()); 1286 for_loop.BreakUnless(jsgraph()->TrueConstant());
1287 } 1287 }
1288 VisitIterationBody(stmt, &for_loop); 1288 VisitIterationBody(stmt, &for_loop);
1289 for_loop.EndBody(); 1289 for_loop.EndBody();
1290 VisitIfNotNull(stmt->next()); 1290 VisitIfNotNull(stmt->next());
1291 for_loop.EndLoop(); 1291 for_loop.EndLoop();
1292 } 1292 }
1293 1293
1294 1294
1295 // TODO(dcarney): this is a big function. Try to clean up some.
1296 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 1295 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1297 VisitForValue(stmt->subject()); 1296 VisitForValue(stmt->subject());
1298 Node* obj = environment()->Pop(); 1297 Node* object = environment()->Pop();
1299 // Check for undefined or null before entering loop. 1298 BlockBuilder for_block(this);
1300 IfBuilder is_undefined(this); 1299 for_block.BeginBlock();
1301 Node* is_undefined_cond = 1300 // Check for null or undefined before entering loop.
1302 NewNode(javascript()->StrictEqual(), obj, jsgraph()->UndefinedConstant()); 1301 Node* is_null_cond =
1303 is_undefined.If(is_undefined_cond); 1302 NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
1304 is_undefined.Then(); 1303 for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1305 is_undefined.Else(); 1304 Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
1305 jsgraph()->UndefinedConstant());
1306 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
1306 { 1307 {
1307 IfBuilder is_null(this);
1308 Node* is_null_cond =
1309 NewNode(javascript()->StrictEqual(), obj, jsgraph()->NullConstant());
1310 is_null.If(is_null_cond);
1311 is_null.Then();
1312 is_null.Else();
1313 // Convert object to jsobject. 1308 // Convert object to jsobject.
1314 // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 1309 object = BuildToObject(object, stmt->ToObjectId());
1315 obj = NewNode(javascript()->ToObject(), obj); 1310 environment()->Push(object);
1316 PrepareFrameState(obj, stmt->ToObjectId(), OutputFrameStateCombine::Push()); 1311
1317 environment()->Push(obj); 1312 // Prepare for-in cache.
1318 // TODO(dcarney): should do a fast enum cache check here to skip runtime. 1313 Node* prepare = NewNode(javascript()->ForInPrepare(), object);
1319 Node* cache_type = NewNode( 1314 PrepareFrameState(prepare, stmt->EnumId(), OutputFrameStateCombine::Push());
1320 javascript()->CallRuntime(Runtime::kGetPropertyNamesFast, 1), obj); 1315 Node* cache_type = NewNode(common()->Projection(0), prepare);
1321 PrepareFrameState(cache_type, stmt->EnumId(), 1316 Node* cache_array = NewNode(common()->Projection(1), prepare);
1322 OutputFrameStateCombine::Push()); 1317 Node* cache_length = NewNode(common()->Projection(2), prepare);
1323 // TODO(dcarney): these next runtime calls should be removed in favour of 1318
1324 // a few simplified instructions. 1319 // Construct the rest of the environment.
1325 Node* cache_pair = NewNode( 1320 environment()->Push(cache_type);
1326 javascript()->CallRuntime(Runtime::kForInInit, 2), obj, cache_type); 1321 environment()->Push(cache_array);
1327 // cache_type may have been replaced. 1322 environment()->Push(cache_length);
1328 Node* cache_array = NewNode(common()->Projection(0), cache_pair); 1323 environment()->Push(jsgraph()->ZeroConstant());
1329 cache_type = NewNode(common()->Projection(1), cache_pair); 1324
1330 Node* cache_length = 1325 // Build the actual loop body.
1331 NewNode(javascript()->CallRuntime(Runtime::kForInCacheArrayLength, 2), 1326 LoopBuilder for_loop(this);
1332 cache_type, cache_array); 1327 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1333 { 1328 {
1334 // Construct the rest of the environment. 1329 // These stack values are renamed in the case of OSR, so reload them
1335 environment()->Push(cache_type); 1330 // from the environment.
1336 environment()->Push(cache_array); 1331 Node* index = environment()->Peek(0);
1337 environment()->Push(cache_length); 1332 Node* cache_length = environment()->Peek(1);
1338 environment()->Push(jsgraph()->ZeroConstant()); 1333 Node* cache_array = environment()->Peek(2);
1334 Node* cache_type = environment()->Peek(3);
1335 Node* object = environment()->Peek(4);
1339 1336
1340 // Build the actual loop body. 1337 // Check loop termination condition.
1341 VisitForInBody(stmt); 1338 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1339 for_loop.BreakWhen(exit_cond);
1340
1341 // Compute the next enumerated value.
1342 Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1343 cache_type, index);
1344 PrepareFrameState(value, stmt->FilterId(),
1345 OutputFrameStateCombine::Push());
1346 IfBuilder test_value(this);
1347 Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
1348 jsgraph()->UndefinedConstant());
1349 test_value.If(test_value_cond, BranchHint::kFalse);
1350 test_value.Then();
1351 test_value.Else();
1352 {
1353 // Bind value and do loop body.
1354 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId());
1355 VisitIterationBody(stmt, &for_loop);
1356 }
1357 test_value.End();
1358 index = environment()->Peek(0);
1359 for_loop.EndBody();
1360
1361 // Increment counter and continue.
1362 index = NewNode(javascript()->ForInStep(), index);
1363 environment()->Poke(0, index);
1342 } 1364 }
1343 is_null.End(); 1365 for_loop.EndLoop();
1366 environment()->Drop(5);
1344 } 1367 }
1345 is_undefined.End(); 1368 for_block.EndBlock();
1346 } 1369 }
1347 1370
1348 1371
1349 // TODO(dcarney): this is a big function. Try to clean up some.
1350 void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) {
1351 LoopBuilder for_loop(this);
1352 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1353
1354 // These stack values are renamed in the case of OSR, so reload them
1355 // from the environment.
1356 Node* index = environment()->Peek(0);
1357 Node* cache_length = environment()->Peek(1);
1358 Node* cache_array = environment()->Peek(2);
1359 Node* cache_type = environment()->Peek(3);
1360 Node* obj = environment()->Peek(4);
1361
1362 // Check loop termination condition (cannot deoptimize).
1363 {
1364 FrameStateBeforeAndAfter states(this, BailoutId::None());
1365 Node* exit_cond = NewNode(javascript()->LessThan(LanguageMode::SLOPPY),
1366 index, cache_length);
1367 states.AddToNode(exit_cond, BailoutId::None(),
1368 OutputFrameStateCombine::Ignore());
1369 for_loop.BreakUnless(exit_cond);
1370 }
1371 Node* pair = NewNode(javascript()->CallRuntime(Runtime::kForInNext, 4), obj,
1372 cache_array, cache_type, index);
1373 Node* value = NewNode(common()->Projection(0), pair);
1374 Node* should_filter = NewNode(common()->Projection(1), pair);
1375 environment()->Push(value);
1376 {
1377 // Test if FILTER_KEY needs to be called.
1378 IfBuilder test_should_filter(this);
1379 Node* should_filter_cond = NewNode(
1380 javascript()->StrictEqual(), should_filter, jsgraph()->TrueConstant());
1381 test_should_filter.If(should_filter_cond);
1382 test_should_filter.Then();
1383 value = environment()->Pop();
1384 Node* builtins = BuildLoadBuiltinsObject();
1385 Node* function = BuildLoadObjectField(
1386 builtins,
1387 JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY));
1388 // result is either the string key or Smi(0) indicating the property
1389 // is gone.
1390 Node* res = NewNode(
1391 javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode()),
1392 function, obj, value);
1393 PrepareFrameState(res, stmt->FilterId(), OutputFrameStateCombine::Push());
1394 Node* property_missing =
1395 NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant());
1396 {
1397 IfBuilder is_property_missing(this);
1398 is_property_missing.If(property_missing);
1399 is_property_missing.Then();
1400 // Inc counter and continue (cannot deoptimize).
1401 {
1402 FrameStateBeforeAndAfter states(this, BailoutId::None());
1403 Node* index_inc = NewNode(javascript()->Add(LanguageMode::SLOPPY),
1404 index, jsgraph()->OneConstant());
1405 states.AddToNode(index_inc, BailoutId::None(),
1406 OutputFrameStateCombine::Ignore());
1407 environment()->Poke(0, index_inc);
1408 }
1409 for_loop.Continue();
1410 is_property_missing.Else();
1411 is_property_missing.End();
1412 }
1413 // Replace 'value' in environment.
1414 environment()->Push(res);
1415 test_should_filter.Else();
1416 test_should_filter.End();
1417 }
1418 value = environment()->Pop();
1419 // Bind value and do loop body.
1420 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId());
1421 VisitIterationBody(stmt, &for_loop);
1422 index = environment()->Peek(0);
1423 for_loop.EndBody();
1424
1425 // Inc counter and continue (cannot deoptimize).
1426 {
1427 FrameStateBeforeAndAfter states(this, BailoutId::None());
1428 Node* index_inc = NewNode(javascript()->Add(LanguageMode::SLOPPY), index,
1429 jsgraph()->OneConstant());
1430 states.AddToNode(index_inc, BailoutId::None(),
1431 OutputFrameStateCombine::Ignore());
1432 environment()->Poke(0, index_inc);
1433 }
1434 for_loop.EndLoop();
1435 environment()->Drop(5);
1436 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1437 }
1438
1439
1440 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { 1372 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
1441 LoopBuilder for_loop(this); 1373 LoopBuilder for_loop(this);
1442 VisitForEffect(stmt->assign_iterator()); 1374 VisitForEffect(stmt->assign_iterator());
1443 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); 1375 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1444 VisitForEffect(stmt->next_result()); 1376 VisitForEffect(stmt->next_result());
1445 VisitForTest(stmt->result_done()); 1377 VisitForTest(stmt->result_done());
1446 Node* condition = environment()->Pop(); 1378 Node* condition = environment()->Pop();
1447 for_loop.BreakWhen(condition); 1379 for_loop.BreakWhen(condition);
1448 VisitForEffect(stmt->assign_each()); 1380 VisitForEffect(stmt->assign_each());
1449 VisitIterationBody(stmt, &for_loop); 1381 VisitIterationBody(stmt, &for_loop);
(...skipping 1882 matching lines...) Expand 10 before | Expand all | Expand 10 after
3332 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { 3264 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3333 // TODO(turbofan): Possible optimization is to NOP on name constants. But the 3265 // TODO(turbofan): Possible optimization is to NOP on name constants. But the
3334 // same caveat as with BuildToBoolean applies, and it should be factored out 3266 // same caveat as with BuildToBoolean applies, and it should be factored out
3335 // into a JSOperatorReducer. 3267 // into a JSOperatorReducer.
3336 Node* name = NewNode(javascript()->ToName(), input); 3268 Node* name = NewNode(javascript()->ToName(), input);
3337 PrepareFrameState(name, bailout_id); 3269 PrepareFrameState(name, bailout_id);
3338 return name; 3270 return name;
3339 } 3271 }
3340 3272
3341 3273
3274 Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3275 Node* object = NewNode(javascript()->ToObject(), input);
3276 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3277 return object;
3278 }
3279
3280
3342 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object, 3281 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3343 Expression* expr) { 3282 Expression* expr) {
3344 if (!FunctionLiteral::NeedsHomeObject(expr)) return value; 3283 if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3345 Handle<Name> name = isolate()->factory()->home_object_symbol(); 3284 Handle<Name> name = isolate()->factory()->home_object_symbol();
3346 FrameStateBeforeAndAfter states(this, BailoutId::None()); 3285 FrameStateBeforeAndAfter states(this, BailoutId::None());
3347 Node* store = 3286 Node* store =
3348 BuildNamedStore(value, name, home_object, TypeFeedbackId::None()); 3287 BuildNamedStore(value, name, home_object, TypeFeedbackId::None());
3349 states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore()); 3288 states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
3350 return store; 3289 return store;
3351 } 3290 }
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
3785 // Phi does not exist yet, introduce one. 3724 // Phi does not exist yet, introduce one.
3786 value = NewPhi(inputs, value, control); 3725 value = NewPhi(inputs, value, control);
3787 value->ReplaceInput(inputs - 1, other); 3726 value->ReplaceInput(inputs - 1, other);
3788 } 3727 }
3789 return value; 3728 return value;
3790 } 3729 }
3791 3730
3792 } // namespace compiler 3731 } // namespace compiler
3793 } // namespace internal 3732 } // namespace internal
3794 } // namespace v8 3733 } // namespace v8
OLDNEW
« 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