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 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 } | 274 } |
275 | 275 |
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 return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2); | 284 return owner_->NewNode( |
| 285 owner_->javascript()->StrictEqual(CompareOperationHints::Any()), t1, |
| 286 t2); |
285 } | 287 } |
286 | 288 |
287 private: | 289 private: |
288 TokenDispenserForFinally dispenser_; | 290 TokenDispenserForFinally dispenser_; |
289 AstGraphBuilder* owner_; | 291 AstGraphBuilder* owner_; |
290 ZoneVector<Entry> deferred_; | 292 ZoneVector<Entry> deferred_; |
291 Node* return_token_; | 293 Node* return_token_; |
292 Node* throw_token_; | 294 Node* throw_token_; |
293 }; | 295 }; |
294 | 296 |
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 if (clause->is_default()) { | 1298 if (clause->is_default()) { |
1297 default_index = i; | 1299 default_index = i; |
1298 continue; | 1300 continue; |
1299 } | 1301 } |
1300 | 1302 |
1301 // Create nodes to perform label comparison as if via '==='. The switch | 1303 // Create nodes to perform label comparison as if via '==='. The switch |
1302 // value is still on the operand stack while the label is evaluated. | 1304 // value is still on the operand stack while the label is evaluated. |
1303 VisitForValue(clause->label()); | 1305 VisitForValue(clause->label()); |
1304 Node* label = environment()->Pop(); | 1306 Node* label = environment()->Pop(); |
1305 Node* tag = environment()->Top(); | 1307 Node* tag = environment()->Top(); |
1306 const Operator* op = javascript()->StrictEqual(); | 1308 |
| 1309 CompareOperationHints hints; |
| 1310 if (!type_hint_analysis_ || |
| 1311 !type_hint_analysis_->GetCompareOperationHints(clause->CompareId(), |
| 1312 &hints)) { |
| 1313 hints = CompareOperationHints::Any(); |
| 1314 } |
| 1315 |
| 1316 const Operator* op = javascript()->StrictEqual(hints); |
1307 Node* condition = NewNode(op, tag, label); | 1317 Node* condition = NewNode(op, tag, label); |
1308 compare_switch.BeginLabel(i, condition); | 1318 compare_switch.BeginLabel(i, condition); |
1309 | 1319 |
1310 // Discard the switch value at label match. | 1320 // Discard the switch value at label match. |
1311 environment()->Pop(); | 1321 environment()->Pop(); |
1312 compare_switch.EndLabel(); | 1322 compare_switch.EndLabel(); |
1313 } | 1323 } |
1314 | 1324 |
1315 // Discard the switch value and mark the default case. | 1325 // Discard the switch value and mark the default case. |
1316 environment()->Pop(); | 1326 environment()->Pop(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 } | 1382 } |
1373 | 1383 |
1374 | 1384 |
1375 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 1385 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
1376 VisitForValue(stmt->subject()); | 1386 VisitForValue(stmt->subject()); |
1377 Node* object = environment()->Pop(); | 1387 Node* object = environment()->Pop(); |
1378 BlockBuilder for_block(this); | 1388 BlockBuilder for_block(this); |
1379 for_block.BeginBlock(); | 1389 for_block.BeginBlock(); |
1380 // Check for null or undefined before entering loop. | 1390 // Check for null or undefined before entering loop. |
1381 Node* is_null_cond = | 1391 Node* is_null_cond = |
1382 NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant()); | 1392 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object, |
| 1393 jsgraph()->NullConstant()); |
1383 for_block.BreakWhen(is_null_cond, BranchHint::kFalse); | 1394 for_block.BreakWhen(is_null_cond, BranchHint::kFalse); |
1384 Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object, | 1395 Node* is_undefined_cond = |
1385 jsgraph()->UndefinedConstant()); | 1396 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object, |
| 1397 jsgraph()->UndefinedConstant()); |
1386 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse); | 1398 for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse); |
1387 { | 1399 { |
1388 // Convert object to jsobject. | 1400 // Convert object to jsobject. |
1389 object = BuildToObject(object, stmt->ToObjectId()); | 1401 object = BuildToObject(object, stmt->ToObjectId()); |
1390 environment()->Push(object); | 1402 environment()->Push(object); |
1391 | 1403 |
1392 // Prepare for-in cache. | 1404 // Prepare for-in cache. |
1393 Node* prepare = NewNode(javascript()->ForInPrepare(), object); | 1405 Node* prepare = NewNode(javascript()->ForInPrepare(), object); |
1394 PrepareFrameState(prepare, stmt->PrepareId(), | 1406 PrepareFrameState(prepare, stmt->PrepareId(), |
1395 OutputFrameStateCombine::Push(3)); | 1407 OutputFrameStateCombine::Push(3)); |
(...skipping 22 matching lines...) Expand all Loading... |
1418 // Check loop termination condition. | 1430 // Check loop termination condition. |
1419 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length); | 1431 Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length); |
1420 for_loop.BreakWhen(exit_cond); | 1432 for_loop.BreakWhen(exit_cond); |
1421 | 1433 |
1422 // Compute the next enumerated value. | 1434 // Compute the next enumerated value. |
1423 Node* value = NewNode(javascript()->ForInNext(), object, cache_array, | 1435 Node* value = NewNode(javascript()->ForInNext(), object, cache_array, |
1424 cache_type, index); | 1436 cache_type, index); |
1425 PrepareFrameState(value, stmt->FilterId(), | 1437 PrepareFrameState(value, stmt->FilterId(), |
1426 OutputFrameStateCombine::Push()); | 1438 OutputFrameStateCombine::Push()); |
1427 IfBuilder test_value(this); | 1439 IfBuilder test_value(this); |
1428 Node* test_value_cond = NewNode(javascript()->StrictEqual(), value, | 1440 Node* test_value_cond = |
1429 jsgraph()->UndefinedConstant()); | 1441 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), |
| 1442 value, jsgraph()->UndefinedConstant()); |
1430 test_value.If(test_value_cond, BranchHint::kFalse); | 1443 test_value.If(test_value_cond, BranchHint::kFalse); |
1431 test_value.Then(); | 1444 test_value.Then(); |
1432 test_value.Else(); | 1445 test_value.Else(); |
1433 { | 1446 { |
1434 // Bind value and do loop body. | 1447 // Bind value and do loop body. |
1435 VectorSlotPair feedback = | 1448 VectorSlotPair feedback = |
1436 CreateVectorSlotPair(stmt->EachFeedbackSlot()); | 1449 CreateVectorSlotPair(stmt->EachFeedbackSlot()); |
1437 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(), | 1450 VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(), |
1438 stmt->AssignmentId()); | 1451 stmt->AssignmentId()); |
1439 VisitIterationBody(stmt, &for_loop); | 1452 VisitIterationBody(stmt, &for_loop); |
(...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2824 } | 2837 } |
2825 } | 2838 } |
2826 } | 2839 } |
2827 | 2840 |
2828 void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr, | 2841 void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr, |
2829 Expression* sub_expr, | 2842 Expression* sub_expr, |
2830 Node* nil_value) { | 2843 Node* nil_value) { |
2831 const Operator* op = nullptr; | 2844 const Operator* op = nullptr; |
2832 switch (expr->op()) { | 2845 switch (expr->op()) { |
2833 case Token::EQ: | 2846 case Token::EQ: |
2834 op = javascript()->Equal(); | 2847 op = javascript()->Equal(CompareOperationHints::Any()); |
2835 break; | 2848 break; |
2836 case Token::EQ_STRICT: | 2849 case Token::EQ_STRICT: |
2837 op = javascript()->StrictEqual(); | 2850 op = javascript()->StrictEqual(CompareOperationHints::Any()); |
2838 break; | 2851 break; |
2839 default: | 2852 default: |
2840 UNREACHABLE(); | 2853 UNREACHABLE(); |
2841 } | 2854 } |
2842 VisitForValue(sub_expr); | 2855 VisitForValue(sub_expr); |
2843 PrepareEagerCheckpoint(sub_expr->id()); | 2856 PrepareEagerCheckpoint(sub_expr->id()); |
2844 Node* value_to_compare = environment()->Pop(); | 2857 Node* value_to_compare = environment()->Pop(); |
2845 Node* value = NewNode(op, value_to_compare, nil_value); | 2858 Node* value = NewNode(op, value_to_compare, nil_value); |
2846 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 2859 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
2847 return ast_context()->ProduceValue(value); | 2860 return ast_context()->ProduceValue(value); |
2848 } | 2861 } |
2849 | 2862 |
2850 void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr, | 2863 void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr, |
2851 Expression* sub_expr, | 2864 Expression* sub_expr, |
2852 Handle<String> check) { | 2865 Handle<String> check) { |
2853 VisitTypeofExpression(sub_expr); | 2866 VisitTypeofExpression(sub_expr); |
2854 PrepareEagerCheckpoint(sub_expr->id()); | 2867 PrepareEagerCheckpoint(sub_expr->id()); |
2855 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop()); | 2868 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop()); |
2856 Node* value = NewNode(javascript()->StrictEqual(), typeof_arg, | 2869 Node* value = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), |
2857 jsgraph()->Constant(check)); | 2870 typeof_arg, jsgraph()->Constant(check)); |
2858 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); | 2871 PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); |
2859 return ast_context()->ProduceValue(value); | 2872 return ast_context()->ProduceValue(value); |
2860 } | 2873 } |
2861 | 2874 |
2862 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 2875 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
2863 // Check for a few fast cases. The AST visiting behavior must be in sync | 2876 // Check for a few fast cases. The AST visiting behavior must be in sync |
2864 // with the full codegen: We don't push both left and right values onto | 2877 // with the full codegen: We don't push both left and right values onto |
2865 // the expression stack when one side is a special-case literal. | 2878 // the expression stack when one side is a special-case literal. |
2866 Expression* sub_expr = nullptr; | 2879 Expression* sub_expr = nullptr; |
2867 Handle<String> check; | 2880 Handle<String> check; |
2868 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 2881 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
2869 return VisitLiteralCompareTypeof(expr, sub_expr, check); | 2882 return VisitLiteralCompareTypeof(expr, sub_expr, check); |
2870 } | 2883 } |
2871 if (expr->IsLiteralCompareUndefined(&sub_expr)) { | 2884 if (expr->IsLiteralCompareUndefined(&sub_expr)) { |
2872 return VisitLiteralCompareNil(expr, sub_expr, | 2885 return VisitLiteralCompareNil(expr, sub_expr, |
2873 jsgraph()->UndefinedConstant()); | 2886 jsgraph()->UndefinedConstant()); |
2874 } | 2887 } |
2875 if (expr->IsLiteralCompareNull(&sub_expr)) { | 2888 if (expr->IsLiteralCompareNull(&sub_expr)) { |
2876 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant()); | 2889 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant()); |
2877 } | 2890 } |
2878 | 2891 |
| 2892 CompareOperationHints hints; |
| 2893 if (!type_hint_analysis_ || |
| 2894 !type_hint_analysis_->GetCompareOperationHints( |
| 2895 expr->CompareOperationFeedbackId(), &hints)) { |
| 2896 hints = CompareOperationHints::Any(); |
| 2897 } |
| 2898 |
2879 const Operator* op; | 2899 const Operator* op; |
2880 switch (expr->op()) { | 2900 switch (expr->op()) { |
2881 case Token::EQ: | 2901 case Token::EQ: |
2882 op = javascript()->Equal(); | 2902 op = javascript()->Equal(hints); |
2883 break; | 2903 break; |
2884 case Token::NE: | 2904 case Token::NE: |
2885 op = javascript()->NotEqual(); | 2905 op = javascript()->NotEqual(hints); |
2886 break; | 2906 break; |
2887 case Token::EQ_STRICT: | 2907 case Token::EQ_STRICT: |
2888 op = javascript()->StrictEqual(); | 2908 op = javascript()->StrictEqual(hints); |
2889 break; | 2909 break; |
2890 case Token::NE_STRICT: | 2910 case Token::NE_STRICT: |
2891 op = javascript()->StrictNotEqual(); | 2911 op = javascript()->StrictNotEqual(hints); |
2892 break; | 2912 break; |
2893 case Token::LT: | 2913 case Token::LT: |
2894 op = javascript()->LessThan(); | 2914 op = javascript()->LessThan(hints); |
2895 break; | 2915 break; |
2896 case Token::GT: | 2916 case Token::GT: |
2897 op = javascript()->GreaterThan(); | 2917 op = javascript()->GreaterThan(hints); |
2898 break; | 2918 break; |
2899 case Token::LTE: | 2919 case Token::LTE: |
2900 op = javascript()->LessThanOrEqual(); | 2920 op = javascript()->LessThanOrEqual(hints); |
2901 break; | 2921 break; |
2902 case Token::GTE: | 2922 case Token::GTE: |
2903 op = javascript()->GreaterThanOrEqual(); | 2923 op = javascript()->GreaterThanOrEqual(hints); |
2904 break; | 2924 break; |
2905 case Token::INSTANCEOF: | 2925 case Token::INSTANCEOF: |
2906 op = javascript()->InstanceOf(); | 2926 op = javascript()->InstanceOf(); |
2907 break; | 2927 break; |
2908 case Token::IN: | 2928 case Token::IN: |
2909 op = javascript()->HasProperty(); | 2929 op = javascript()->HasProperty(); |
2910 break; | 2930 break; |
2911 default: | 2931 default: |
2912 op = nullptr; | 2932 op = nullptr; |
2913 UNREACHABLE(); | 2933 UNREACHABLE(); |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3312 BailoutId::None()); | 3332 BailoutId::None()); |
3313 return object; | 3333 return object; |
3314 } | 3334 } |
3315 | 3335 |
3316 | 3336 |
3317 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable, | 3337 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable, |
3318 Node* not_hole, | 3338 Node* not_hole, |
3319 BailoutId bailout_id) { | 3339 BailoutId bailout_id) { |
3320 IfBuilder hole_check(this); | 3340 IfBuilder hole_check(this); |
3321 Node* the_hole = jsgraph()->TheHoleConstant(); | 3341 Node* the_hole = jsgraph()->TheHoleConstant(); |
3322 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); | 3342 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), |
| 3343 value, the_hole); |
3323 hole_check.If(check); | 3344 hole_check.If(check); |
3324 hole_check.Then(); | 3345 hole_check.Then(); |
3325 Node* error = BuildThrowReferenceError(variable, bailout_id); | 3346 Node* error = BuildThrowReferenceError(variable, bailout_id); |
3326 environment()->Push(error); | 3347 environment()->Push(error); |
3327 hole_check.Else(); | 3348 hole_check.Else(); |
3328 environment()->Push(not_hole); | 3349 environment()->Push(not_hole); |
3329 hole_check.End(); | 3350 hole_check.End(); |
3330 return environment()->Pop(); | 3351 return environment()->Pop(); |
3331 } | 3352 } |
3332 | 3353 |
3333 | 3354 |
3334 Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable, | 3355 Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable, |
3335 Node* for_hole, | 3356 Node* for_hole, |
3336 BailoutId bailout_id) { | 3357 BailoutId bailout_id) { |
3337 IfBuilder hole_check(this); | 3358 IfBuilder hole_check(this); |
3338 Node* the_hole = jsgraph()->TheHoleConstant(); | 3359 Node* the_hole = jsgraph()->TheHoleConstant(); |
3339 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); | 3360 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), |
| 3361 value, the_hole); |
3340 hole_check.If(check); | 3362 hole_check.If(check); |
3341 hole_check.Then(); | 3363 hole_check.Then(); |
3342 environment()->Push(for_hole); | 3364 environment()->Push(for_hole); |
3343 hole_check.Else(); | 3365 hole_check.Else(); |
3344 Node* error = BuildThrowReferenceError(variable, bailout_id); | 3366 Node* error = BuildThrowReferenceError(variable, bailout_id); |
3345 environment()->Push(error); | 3367 environment()->Push(error); |
3346 hole_check.End(); | 3368 hole_check.End(); |
3347 return environment()->Pop(); | 3369 return environment()->Pop(); |
3348 } | 3370 } |
3349 | 3371 |
3350 | 3372 |
3351 Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name, | 3373 Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name, |
3352 BailoutId bailout_id) { | 3374 BailoutId bailout_id) { |
3353 IfBuilder prototype_check(this); | 3375 IfBuilder prototype_check(this); |
3354 Node* prototype_string = | 3376 Node* prototype_string = |
3355 jsgraph()->Constant(isolate()->factory()->prototype_string()); | 3377 jsgraph()->Constant(isolate()->factory()->prototype_string()); |
3356 Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string); | 3378 Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), |
| 3379 name, prototype_string); |
3357 prototype_check.If(check); | 3380 prototype_check.If(check); |
3358 prototype_check.Then(); | 3381 prototype_check.Then(); |
3359 Node* error = BuildThrowStaticPrototypeError(bailout_id); | 3382 Node* error = BuildThrowStaticPrototypeError(bailout_id); |
3360 environment()->Push(error); | 3383 environment()->Push(error); |
3361 prototype_check.Else(); | 3384 prototype_check.Else(); |
3362 environment()->Push(name); | 3385 environment()->Push(name); |
3363 prototype_check.End(); | 3386 prototype_check.End(); |
3364 return environment()->Pop(); | 3387 return environment()->Pop(); |
3365 } | 3388 } |
3366 | 3389 |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3896 environment()->Pop(); | 3919 environment()->Pop(); |
3897 fast_block.BeginBlock(); | 3920 fast_block.BeginBlock(); |
3898 | 3921 |
3899 // Perform checks whether the fast mode applies, by looking for any | 3922 // Perform checks whether the fast mode applies, by looking for any |
3900 // extension object which might shadow the optimistic declaration. | 3923 // extension object which might shadow the optimistic declaration. |
3901 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { | 3924 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { |
3902 if ((bitset & 1) == 0) continue; | 3925 if ((bitset & 1) == 0) continue; |
3903 Node* load = NewNode( | 3926 Node* load = NewNode( |
3904 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), | 3927 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), |
3905 current_context()); | 3928 current_context()); |
3906 Node* check = NewNode(javascript()->StrictEqual(), load, | 3929 Node* check = |
3907 jsgraph()->TheHoleConstant()); | 3930 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load, |
| 3931 jsgraph()->TheHoleConstant()); |
3908 fast_block.BreakUnless(check, BranchHint::kTrue); | 3932 fast_block.BreakUnless(check, BranchHint::kTrue); |
3909 } | 3933 } |
3910 | 3934 |
3911 // Fast case, because variable is not shadowed. | 3935 // Fast case, because variable is not shadowed. |
3912 if (Node* constant = TryLoadGlobalConstant(name)) { | 3936 if (Node* constant = TryLoadGlobalConstant(name)) { |
3913 environment()->Push(constant); | 3937 environment()->Push(constant); |
3914 } else { | 3938 } else { |
3915 // Perform global slot load. | 3939 // Perform global slot load. |
3916 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode); | 3940 Node* fast = BuildGlobalLoad(name, feedback, typeof_mode); |
3917 PrepareFrameState(fast, bailout_id, combine); | 3941 PrepareFrameState(fast, bailout_id, combine); |
(...skipping 24 matching lines...) Expand all Loading... |
3942 environment()->Pop(); | 3966 environment()->Pop(); |
3943 fast_block.BeginBlock(); | 3967 fast_block.BeginBlock(); |
3944 | 3968 |
3945 // Perform checks whether the fast mode applies, by looking for any | 3969 // Perform checks whether the fast mode applies, by looking for any |
3946 // extension object which might shadow the optimistic declaration. | 3970 // extension object which might shadow the optimistic declaration. |
3947 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { | 3971 for (int depth = 0; bitset != 0; bitset >>= 1, depth++) { |
3948 if ((bitset & 1) == 0) continue; | 3972 if ((bitset & 1) == 0) continue; |
3949 Node* load = NewNode( | 3973 Node* load = NewNode( |
3950 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), | 3974 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), |
3951 current_context()); | 3975 current_context()); |
3952 Node* check = NewNode(javascript()->StrictEqual(), load, | 3976 Node* check = |
3953 jsgraph()->TheHoleConstant()); | 3977 NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load, |
| 3978 jsgraph()->TheHoleConstant()); |
3954 fast_block.BreakUnless(check, BranchHint::kTrue); | 3979 fast_block.BreakUnless(check, BranchHint::kTrue); |
3955 } | 3980 } |
3956 | 3981 |
3957 // Fast case, because variable is not shadowed. Perform context slot load. | 3982 // Fast case, because variable is not shadowed. Perform context slot load. |
3958 Variable* local = variable->local_if_not_shadowed(); | 3983 Variable* local = variable->local_if_not_shadowed(); |
3959 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context. | 3984 DCHECK(local->location() == VariableLocation::CONTEXT); // Must be context. |
3960 Node* fast = | 3985 Node* fast = |
3961 BuildVariableLoad(local, bailout_id, feedback, combine, typeof_mode); | 3986 BuildVariableLoad(local, bailout_id, feedback, combine, typeof_mode); |
3962 environment()->Push(fast); | 3987 environment()->Push(fast); |
3963 slow_block.Break(); | 3988 slow_block.Break(); |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4362 // Phi does not exist yet, introduce one. | 4387 // Phi does not exist yet, introduce one. |
4363 value = NewPhi(inputs, value, control); | 4388 value = NewPhi(inputs, value, control); |
4364 value->ReplaceInput(inputs - 1, other); | 4389 value->ReplaceInput(inputs - 1, other); |
4365 } | 4390 } |
4366 return value; | 4391 return value; |
4367 } | 4392 } |
4368 | 4393 |
4369 } // namespace compiler | 4394 } // namespace compiler |
4370 } // namespace internal | 4395 } // namespace internal |
4371 } // namespace v8 | 4396 } // namespace v8 |
OLD | NEW |