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

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 2035383003: [turbofan] Type feedback for numeric comparisons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fixes Created 4 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 | « no previous file | src/compiler/bytecode-graph-builder.cc » ('j') | src/compiler/js-operator.cc » ('J')
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/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/compiler/ast-loop-assignment-analyzer.h" 9 #include "src/compiler/ast-loop-assignment-analyzer.h"
10 #include "src/compiler/control-builders.h" 10 #include "src/compiler/control-builders.h"
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 protected: 276 protected:
277 Node* NewPathToken(int token_id) { 277 Node* NewPathToken(int token_id) {
278 return owner_->jsgraph()->Constant(token_id); 278 return owner_->jsgraph()->Constant(token_id);
279 } 279 }
280 Node* NewPathTokenForImplicitFallThrough() { 280 Node* NewPathTokenForImplicitFallThrough() {
281 return NewPathToken(TokenDispenserForFinally::kFallThroughToken); 281 return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
282 } 282 }
283 Node* NewPathDispatchCondition(Node* t1, Node* t2) { 283 Node* NewPathDispatchCondition(Node* t1, Node* t2) {
284 // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi 284 // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
285 // nodes all have kRepTagged|kTypeAny, which causes representation mismatch. 285 // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
286 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2); 286 return owner_->NewNode(
287 owner_->javascript()->StrictEqual(CompareOperationHints::Any()), t1,
288 t2);
287 } 289 }
288 290
289 private: 291 private:
290 TokenDispenserForFinally dispenser_; 292 TokenDispenserForFinally dispenser_;
291 AstGraphBuilder* owner_; 293 AstGraphBuilder* owner_;
292 ZoneVector<Entry> deferred_; 294 ZoneVector<Entry> deferred_;
293 Node* return_token_; 295 Node* return_token_;
294 Node* throw_token_; 296 Node* throw_token_;
295 }; 297 };
296 298
(...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after
1302 if (clause->is_default()) { 1304 if (clause->is_default()) {
1303 default_index = i; 1305 default_index = i;
1304 continue; 1306 continue;
1305 } 1307 }
1306 1308
1307 // Create nodes to perform label comparison as if via '==='. The switch 1309 // Create nodes to perform label comparison as if via '==='. The switch
1308 // value is still on the operand stack while the label is evaluated. 1310 // value is still on the operand stack while the label is evaluated.
1309 VisitForValue(clause->label()); 1311 VisitForValue(clause->label());
1310 Node* label = environment()->Pop(); 1312 Node* label = environment()->Pop();
1311 Node* tag = environment()->Top(); 1313 Node* tag = environment()->Top();
1312 const Operator* op = javascript()->StrictEqual(); 1314 const Operator* op =
1315 javascript()->StrictEqual(CompareOperationHints::Any());
Benedikt Meurer 2016/06/07 04:11:00 We do have type feedback for switches. Can you eit
Jarin 2016/06/09 13:37:31 Done.
1313 Node* condition = NewNode(op, tag, label); 1316 Node* condition = NewNode(op, tag, label);
1314 compare_switch.BeginLabel(i, condition); 1317 compare_switch.BeginLabel(i, condition);
1315 1318
1316 // Discard the switch value at label match. 1319 // Discard the switch value at label match.
1317 environment()->Pop(); 1320 environment()->Pop();
1318 compare_switch.EndLabel(); 1321 compare_switch.EndLabel();
1319 } 1322 }
1320 1323
1321 // Discard the switch value and mark the default case. 1324 // Discard the switch value and mark the default case.
1322 environment()->Pop(); 1325 environment()->Pop();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 } 1381 }
1379 1382
1380 1383
1381 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 1384 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1382 VisitForValue(stmt->subject()); 1385 VisitForValue(stmt->subject());
1383 Node* object = environment()->Pop(); 1386 Node* object = environment()->Pop();
1384 BlockBuilder for_block(this); 1387 BlockBuilder for_block(this);
1385 for_block.BeginBlock(); 1388 for_block.BeginBlock();
1386 // Check for null or undefined before entering loop. 1389 // Check for null or undefined before entering loop.
1387 Node* is_null_cond = 1390 Node* is_null_cond =
1388 NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant()); 1391 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object,
1392 jsgraph()->NullConstant());
1389 for_block.BreakWhen(is_null_cond, BranchHint::kFalse); 1393 for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1390 Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object, 1394 Node* is_undefined_cond =
1391 jsgraph()->UndefinedConstant()); 1395 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object,
1396 jsgraph()->UndefinedConstant());
1392 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse); 1397 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
1393 { 1398 {
1394 // Convert object to jsobject. 1399 // Convert object to jsobject.
1395 object = BuildToObject(object, stmt->ToObjectId()); 1400 object = BuildToObject(object, stmt->ToObjectId());
1396 environment()->Push(object); 1401 environment()->Push(object);
1397 1402
1398 // Prepare for-in cache. 1403 // Prepare for-in cache.
1399 Node* prepare = NewNode(javascript()->ForInPrepare(), object); 1404 Node* prepare = NewNode(javascript()->ForInPrepare(), object);
1400 PrepareFrameState(prepare, stmt->PrepareId(), 1405 PrepareFrameState(prepare, stmt->PrepareId(),
1401 OutputFrameStateCombine::Push(3)); 1406 OutputFrameStateCombine::Push(3));
(...skipping 22 matching lines...) Expand all
1424 // Check loop termination condition. 1429 // Check loop termination condition.
1425 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length); 1430 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1426 for_loop.BreakWhen(exit_cond); 1431 for_loop.BreakWhen(exit_cond);
1427 1432
1428 // Compute the next enumerated value. 1433 // Compute the next enumerated value.
1429 Node* value = NewNode(javascript()->ForInNext(), object, cache_array, 1434 Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1430 cache_type, index); 1435 cache_type, index);
1431 PrepareFrameState(value, stmt->FilterId(), 1436 PrepareFrameState(value, stmt->FilterId(),
1432 OutputFrameStateCombine::Push()); 1437 OutputFrameStateCombine::Push());
1433 IfBuilder test_value(this); 1438 IfBuilder test_value(this);
1434 Node* test_value_cond = NewNode(javascript()->StrictEqual(), value, 1439 Node* test_value_cond =
1435 jsgraph()->UndefinedConstant()); 1440 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
1441 value, jsgraph()->UndefinedConstant());
1436 test_value.If(test_value_cond, BranchHint::kFalse); 1442 test_value.If(test_value_cond, BranchHint::kFalse);
1437 test_value.Then(); 1443 test_value.Then();
1438 test_value.Else(); 1444 test_value.Else();
1439 { 1445 {
1440 // Bind value and do loop body. 1446 // Bind value and do loop body.
1441 VectorSlotPair feedback = 1447 VectorSlotPair feedback =
1442 CreateVectorSlotPair(stmt->EachFeedbackSlot()); 1448 CreateVectorSlotPair(stmt->EachFeedbackSlot());
1443 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(), 1449 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(),
1444 stmt->AssignmentId()); 1450 stmt->AssignmentId());
1445 VisitIterationBody(stmt, &for_loop); 1451 VisitIterationBody(stmt, &for_loop);
(...skipping 1393 matching lines...) Expand 10 before | Expand all | Expand 10 after
2839 } 2845 }
2840 } 2846 }
2841 } 2847 }
2842 2848
2843 void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr, 2849 void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
2844 Expression* sub_expr, 2850 Expression* sub_expr,
2845 Node* nil_value) { 2851 Node* nil_value) {
2846 const Operator* op = nullptr; 2852 const Operator* op = nullptr;
2847 switch (expr->op()) { 2853 switch (expr->op()) {
2848 case Token::EQ: 2854 case Token::EQ:
2849 op = javascript()->Equal(); 2855 op = javascript()->Equal(CompareOperationHints::Any());
2850 break; 2856 break;
2851 case Token::EQ_STRICT: 2857 case Token::EQ_STRICT:
2852 op = javascript()->StrictEqual(); 2858 op = javascript()->StrictEqual(CompareOperationHints::Any());
2853 break; 2859 break;
2854 default: 2860 default:
2855 UNREACHABLE(); 2861 UNREACHABLE();
2856 } 2862 }
2857 VisitForValue(sub_expr); 2863 VisitForValue(sub_expr);
2858 FrameStateBeforeAndAfter states(this, sub_expr->id()); 2864 FrameStateBeforeAndAfter states(this, sub_expr->id());
2859 Node* value_to_compare = environment()->Pop(); 2865 Node* value_to_compare = environment()->Pop();
2860 Node* value = NewNode(op, value_to_compare, nil_value); 2866 Node* value = NewNode(op, value_to_compare, nil_value);
2861 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); 2867 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2862 return ast_context()->ProduceValue(value); 2868 return ast_context()->ProduceValue(value);
2863 } 2869 }
2864 2870
2865 void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr, 2871 void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
2866 Expression* sub_expr, 2872 Expression* sub_expr,
2867 Handle<String> check) { 2873 Handle<String> check) {
2868 VisitTypeofExpression(sub_expr); 2874 VisitTypeofExpression(sub_expr);
2869 FrameStateBeforeAndAfter states(this, sub_expr->id()); 2875 FrameStateBeforeAndAfter states(this, sub_expr->id());
2870 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop()); 2876 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
2871 Node* value = NewNode(javascript()->StrictEqual(), typeof_arg, 2877 Node* value = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
2872 jsgraph()->Constant(check)); 2878 typeof_arg, jsgraph()->Constant(check));
2873 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); 2879 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2874 return ast_context()->ProduceValue(value); 2880 return ast_context()->ProduceValue(value);
2875 } 2881 }
2876 2882
2877 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 2883 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
2878 // Check for a few fast cases. The AST visiting behavior must be in sync 2884 // Check for a few fast cases. The AST visiting behavior must be in sync
2879 // with the full codegen: We don't push both left and right values onto 2885 // with the full codegen: We don't push both left and right values onto
2880 // the expression stack when one side is a special-case literal. 2886 // the expression stack when one side is a special-case literal.
2881 Expression* sub_expr = nullptr; 2887 Expression* sub_expr = nullptr;
2882 Handle<String> check; 2888 Handle<String> check;
2883 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { 2889 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
2884 return VisitLiteralCompareTypeof(expr, sub_expr, check); 2890 return VisitLiteralCompareTypeof(expr, sub_expr, check);
2885 } 2891 }
2886 if (expr->IsLiteralCompareUndefined(&sub_expr)) { 2892 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
2887 return VisitLiteralCompareNil(expr, sub_expr, 2893 return VisitLiteralCompareNil(expr, sub_expr,
2888 jsgraph()->UndefinedConstant()); 2894 jsgraph()->UndefinedConstant());
2889 } 2895 }
2890 if (expr->IsLiteralCompareNull(&sub_expr)) { 2896 if (expr->IsLiteralCompareNull(&sub_expr)) {
2891 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant()); 2897 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
2892 } 2898 }
2893 2899
2900 CompareOperationHints hints;
2901 if (!type_hint_analysis_ ||
2902 !type_hint_analysis_->GetCompareOperationHints(
2903 expr->CompareOperationFeedbackId(), &hints)) {
2904 hints = CompareOperationHints::Any();
2905 }
2906
2894 const Operator* op; 2907 const Operator* op;
2895 switch (expr->op()) { 2908 switch (expr->op()) {
2896 case Token::EQ: 2909 case Token::EQ:
2897 op = javascript()->Equal(); 2910 op = javascript()->Equal(hints);
2898 break; 2911 break;
2899 case Token::NE: 2912 case Token::NE:
2900 op = javascript()->NotEqual(); 2913 op = javascript()->NotEqual(hints);
2901 break; 2914 break;
2902 case Token::EQ_STRICT: 2915 case Token::EQ_STRICT:
2903 op = javascript()->StrictEqual(); 2916 op = javascript()->StrictEqual(hints);
2904 break; 2917 break;
2905 case Token::NE_STRICT: 2918 case Token::NE_STRICT:
2906 op = javascript()->StrictNotEqual(); 2919 op = javascript()->StrictNotEqual(hints);
2907 break; 2920 break;
2908 case Token::LT: 2921 case Token::LT:
2909 op = javascript()->LessThan(); 2922 op = javascript()->LessThan(hints);
2910 break; 2923 break;
2911 case Token::GT: 2924 case Token::GT:
2912 op = javascript()->GreaterThan(); 2925 op = javascript()->GreaterThan(hints);
2913 break; 2926 break;
2914 case Token::LTE: 2927 case Token::LTE:
2915 op = javascript()->LessThanOrEqual(); 2928 op = javascript()->LessThanOrEqual(hints);
2916 break; 2929 break;
2917 case Token::GTE: 2930 case Token::GTE:
2918 op = javascript()->GreaterThanOrEqual(); 2931 op = javascript()->GreaterThanOrEqual(hints);
2919 break; 2932 break;
2920 case Token::INSTANCEOF: 2933 case Token::INSTANCEOF:
2921 op = javascript()->InstanceOf(); 2934 op = javascript()->InstanceOf(hints);
2922 break; 2935 break;
2923 case Token::IN: 2936 case Token::IN:
2924 op = javascript()->HasProperty(); 2937 op = javascript()->HasProperty(hints);
2925 break; 2938 break;
2926 default: 2939 default:
2927 op = nullptr; 2940 op = nullptr;
2928 UNREACHABLE(); 2941 UNREACHABLE();
2929 } 2942 }
2930 VisitForValue(expr->left()); 2943 VisitForValue(expr->left());
2931 VisitForValue(expr->right()); 2944 VisitForValue(expr->right());
2932 FrameStateBeforeAndAfter states(this, expr->right()->id()); 2945 FrameStateBeforeAndAfter states(this, expr->right()->id());
2933 Node* right = environment()->Pop(); 2946 Node* right = environment()->Pop();
2934 Node* left = environment()->Pop(); 2947 Node* left = environment()->Pop();
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
3331 BailoutId::None(), states); 3344 BailoutId::None(), states);
3332 return object; 3345 return object;
3333 } 3346 }
3334 3347
3335 3348
3336 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable, 3349 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3337 Node* not_hole, 3350 Node* not_hole,
3338 BailoutId bailout_id) { 3351 BailoutId bailout_id) {
3339 IfBuilder hole_check(this); 3352 IfBuilder hole_check(this);
3340 Node* the_hole = jsgraph()->TheHoleConstant(); 3353 Node* the_hole = jsgraph()->TheHoleConstant();
3341 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); 3354 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
3355 value, the_hole);
3342 hole_check.If(check); 3356 hole_check.If(check);
3343 hole_check.Then(); 3357 hole_check.Then();
3344 Node* error = BuildThrowReferenceError(variable, bailout_id); 3358 Node* error = BuildThrowReferenceError(variable, bailout_id);
3345 environment()->Push(error); 3359 environment()->Push(error);
3346 hole_check.Else(); 3360 hole_check.Else();
3347 environment()->Push(not_hole); 3361 environment()->Push(not_hole);
3348 hole_check.End(); 3362 hole_check.End();
3349 return environment()->Pop(); 3363 return environment()->Pop();
3350 } 3364 }
3351 3365
3352 3366
3353 Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable, 3367 Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3354 Node* for_hole, 3368 Node* for_hole,
3355 BailoutId bailout_id) { 3369 BailoutId bailout_id) {
3356 IfBuilder hole_check(this); 3370 IfBuilder hole_check(this);
3357 Node* the_hole = jsgraph()->TheHoleConstant(); 3371 Node* the_hole = jsgraph()->TheHoleConstant();
3358 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); 3372 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
3373 value, the_hole);
3359 hole_check.If(check); 3374 hole_check.If(check);
3360 hole_check.Then(); 3375 hole_check.Then();
3361 environment()->Push(for_hole); 3376 environment()->Push(for_hole);
3362 hole_check.Else(); 3377 hole_check.Else();
3363 Node* error = BuildThrowReferenceError(variable, bailout_id); 3378 Node* error = BuildThrowReferenceError(variable, bailout_id);
3364 environment()->Push(error); 3379 environment()->Push(error);
3365 hole_check.End(); 3380 hole_check.End();
3366 return environment()->Pop(); 3381 return environment()->Pop();
3367 } 3382 }
3368 3383
3369 3384
3370 Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name, 3385 Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3371 BailoutId bailout_id) { 3386 BailoutId bailout_id) {
3372 IfBuilder prototype_check(this); 3387 IfBuilder prototype_check(this);
3373 Node* prototype_string = 3388 Node* prototype_string =
3374 jsgraph()->Constant(isolate()->factory()->prototype_string()); 3389 jsgraph()->Constant(isolate()->factory()->prototype_string());
3375 Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string); 3390 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
3391 name, prototype_string);
3376 prototype_check.If(check); 3392 prototype_check.If(check);
3377 prototype_check.Then(); 3393 prototype_check.Then();
3378 Node* error = BuildThrowStaticPrototypeError(bailout_id); 3394 Node* error = BuildThrowStaticPrototypeError(bailout_id);
3379 environment()->Push(error); 3395 environment()->Push(error);
3380 prototype_check.Else(); 3396 prototype_check.Else();
3381 environment()->Push(name); 3397 environment()->Push(name);
3382 prototype_check.End(); 3398 prototype_check.End();
3383 return environment()->Pop(); 3399 return environment()->Pop();
3384 } 3400 }
3385 3401
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
3917 environment()->Pop(); 3933 environment()->Pop();
3918 fast_block.BeginBlock(); 3934 fast_block.BeginBlock();
3919 3935
3920 // Perform checks whether the fast mode applies, by looking for any 3936 // Perform checks whether the fast mode applies, by looking for any
3921 // extension object which might shadow the optimistic declaration. 3937 // extension object which might shadow the optimistic declaration.
3922 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { 3938 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3923 if ((bitset & 1) == 0) continue; 3939 if ((bitset & 1) == 0) continue;
3924 Node* load = NewNode( 3940 Node* load = NewNode(
3925 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), 3941 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3926 current_context()); 3942 current_context());
3927 Node* check = NewNode(javascript()->StrictEqual(), load, 3943 Node* check =
3928 jsgraph()->TheHoleConstant()); 3944 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load,
3945 jsgraph()->TheHoleConstant());
3929 fast_block.BreakUnless(check, BranchHint::kTrue); 3946 fast_block.BreakUnless(check, BranchHint::kTrue);
3930 } 3947 }
3931 3948
3932 // Fast case, because variable is not shadowed. 3949 // Fast case, because variable is not shadowed.
3933 if (Node* constant = TryLoadGlobalConstant(name)) { 3950 if (Node* constant = TryLoadGlobalConstant(name)) {
3934 environment()->Push(constant); 3951 environment()->Push(constant);
3935 } else { 3952 } else {
3936 // Perform global slot load. 3953 // Perform global slot load.
3937 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode); 3954 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
3938 states.AddToNode(fast, bailout_id, combine); 3955 states.AddToNode(fast, bailout_id, combine);
(...skipping 24 matching lines...) Expand all
3963 environment()->Pop(); 3980 environment()->Pop();
3964 fast_block.BeginBlock(); 3981 fast_block.BeginBlock();
3965 3982
3966 // Perform checks whether the fast mode applies, by looking for any 3983 // Perform checks whether the fast mode applies, by looking for any
3967 // extension object which might shadow the optimistic declaration. 3984 // extension object which might shadow the optimistic declaration.
3968 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { 3985 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) {
3969 if ((bitset & 1) == 0) continue; 3986 if ((bitset & 1) == 0) continue;
3970 Node* load = NewNode( 3987 Node* load = NewNode(
3971 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), 3988 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3972 current_context()); 3989 current_context());
3973 Node* check = NewNode(javascript()->StrictEqual(), load, 3990 Node* check =
3974 jsgraph()->TheHoleConstant()); 3991 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load,
3992 jsgraph()->TheHoleConstant());
3975 fast_block.BreakUnless(check, BranchHint::kTrue); 3993 fast_block.BreakUnless(check, BranchHint::kTrue);
3976 } 3994 }
3977 3995
3978 // Fast case, because variable is not shadowed. Perform context slot load. 3996 // Fast case, because variable is not shadowed. Perform context slot load.
3979 Variable* local = variable->local_if_not_shadowed(); 3997 Variable* local = variable->local_if_not_shadowed();
3980 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context. 3998 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context.
3981 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine, 3999 Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine,
3982 typeof_mode); 4000 typeof_mode);
3983 environment()->Push(fast); 4001 environment()->Push(fast);
3984 slow_block.Break(); 4002 slow_block.Break();
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
4375 // Phi does not exist yet, introduce one. 4393 // Phi does not exist yet, introduce one.
4376 value = NewPhi(inputs, value, control); 4394 value = NewPhi(inputs, value, control);
4377 value->ReplaceInput(inputs - 1, other); 4395 value->ReplaceInput(inputs - 1, other);
4378 } 4396 }
4379 return value; 4397 return value;
4380 } 4398 }
4381 4399
4382 } // namespace compiler 4400 } // namespace compiler
4383 } // namespace internal 4401 } // namespace internal
4384 } // namespace v8 4402 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/bytecode-graph-builder.cc » ('j') | src/compiler/js-operator.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698