Chromium Code Reviews| 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 |