OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |