| 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/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/control-builders.h" | 8 #include "src/compiler/control-builders.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 stack_dirty_ = false; | 231 stack_dirty_ = false; |
| 232 } | 232 } |
| 233 | 233 |
| 234 Operator* op = common()->FrameState(ast_id); | 234 Operator* op = common()->FrameState(ast_id); |
| 235 | 235 |
| 236 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_); | 236 return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_); |
| 237 } | 237 } |
| 238 | 238 |
| 239 | 239 |
| 240 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, | 240 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, |
| 241 Expression::Context kind) | 241 Expression::Context kind, |
| 242 : kind_(kind), owner_(own), outer_(own->ast_context()) { | 242 BailoutId bailout_id) |
| 243 : bailout_id_(bailout_id), |
| 244 kind_(kind), |
| 245 owner_(own), |
| 246 outer_(own->ast_context()) { |
| 243 owner()->set_ast_context(this); // Push. | 247 owner()->set_ast_context(this); // Push. |
| 244 #ifdef DEBUG | 248 #ifdef DEBUG |
| 245 original_height_ = environment()->stack_height(); | 249 original_height_ = environment()->stack_height(); |
| 246 #endif | 250 #endif |
| 247 } | 251 } |
| 248 | 252 |
| 249 | 253 |
| 250 AstGraphBuilder::AstContext::~AstContext() { | 254 AstGraphBuilder::AstContext::~AstContext() { |
| 251 owner()->set_ast_context(outer_); // Pop. | 255 owner()->set_ast_context(outer_); // Pop. |
| 252 } | 256 } |
| 253 | 257 |
| 254 | 258 |
| 255 AstGraphBuilder::AstEffectContext::~AstEffectContext() { | 259 AstGraphBuilder::AstEffectContext::~AstEffectContext() { |
| 256 DCHECK(environment()->stack_height() == original_height_); | 260 DCHECK(environment()->stack_height() == original_height_); |
| 257 } | 261 } |
| 258 | 262 |
| 259 | 263 |
| 260 AstGraphBuilder::AstValueContext::~AstValueContext() { | 264 AstGraphBuilder::AstValueContext::~AstValueContext() { |
| 261 DCHECK(environment()->stack_height() == original_height_ + 1); | 265 DCHECK(environment()->stack_height() == original_height_ + 1); |
| 262 } | 266 } |
| 263 | 267 |
| 264 | 268 |
| 265 AstGraphBuilder::AstTestContext::~AstTestContext() { | 269 AstGraphBuilder::AstTestContext::~AstTestContext() { |
| 266 DCHECK(environment()->stack_height() == original_height_ + 1); | 270 DCHECK(environment()->stack_height() == original_height_ + 1); |
| 267 } | 271 } |
| 268 | 272 |
| 269 | 273 |
| 274 void AstGraphBuilder::AstEffectContext::ProduceValueWithLazyBailout( |
| 275 Node* value) { |
| 276 ProduceValue(value); |
| 277 owner()->BuildLazyBailout(value, bailout_id_); |
| 278 } |
| 279 |
| 280 |
| 281 void AstGraphBuilder::AstValueContext::ProduceValueWithLazyBailout( |
| 282 Node* value) { |
| 283 ProduceValue(value); |
| 284 owner()->BuildLazyBailout(value, bailout_id_); |
| 285 } |
| 286 |
| 287 |
| 288 void AstGraphBuilder::AstTestContext::ProduceValueWithLazyBailout(Node* value) { |
| 289 environment()->Push(value); |
| 290 owner()->BuildLazyBailout(value, bailout_id_); |
| 291 environment()->Pop(); |
| 292 ProduceValue(value); |
| 293 } |
| 294 |
| 295 |
| 270 void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) { | 296 void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) { |
| 271 // The value is ignored. | 297 // The value is ignored. |
| 272 } | 298 } |
| 273 | 299 |
| 274 | 300 |
| 275 void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) { | 301 void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) { |
| 276 environment()->Push(value); | 302 environment()->Push(value); |
| 277 } | 303 } |
| 278 | 304 |
| 279 | 305 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 | 352 |
| 327 | 353 |
| 328 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) { | 354 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) { |
| 329 for (int i = 0; i < exprs->length(); ++i) { | 355 for (int i = 0; i < exprs->length(); ++i) { |
| 330 VisitForValue(exprs->at(i)); | 356 VisitForValue(exprs->at(i)); |
| 331 } | 357 } |
| 332 } | 358 } |
| 333 | 359 |
| 334 | 360 |
| 335 void AstGraphBuilder::VisitForValue(Expression* expr) { | 361 void AstGraphBuilder::VisitForValue(Expression* expr) { |
| 336 AstValueContext for_value(this); | 362 AstValueContext for_value(this, expr->id()); |
| 337 if (!HasStackOverflow()) { | 363 if (!HasStackOverflow()) { |
| 338 expr->Accept(this); | 364 expr->Accept(this); |
| 339 } | 365 } |
| 340 } | 366 } |
| 341 | 367 |
| 342 | 368 |
| 343 void AstGraphBuilder::VisitForEffect(Expression* expr) { | 369 void AstGraphBuilder::VisitForEffect(Expression* expr) { |
| 344 AstEffectContext for_effect(this); | 370 AstEffectContext for_effect(this, expr->id()); |
| 345 if (!HasStackOverflow()) { | 371 if (!HasStackOverflow()) { |
| 346 expr->Accept(this); | 372 expr->Accept(this); |
| 347 } | 373 } |
| 348 } | 374 } |
| 349 | 375 |
| 350 | 376 |
| 351 void AstGraphBuilder::VisitForTest(Expression* expr) { | 377 void AstGraphBuilder::VisitForTest(Expression* expr) { |
| 352 AstTestContext for_condition(this); | 378 AstTestContext for_condition(this, expr->id()); |
| 353 if (!HasStackOverflow()) { | 379 if (!HasStackOverflow()) { |
| 354 expr->Accept(this); | 380 expr->Accept(this); |
| 355 } | 381 } |
| 356 } | 382 } |
| 357 | 383 |
| 358 | 384 |
| 359 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { | 385 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { |
| 360 Variable* variable = decl->proxy()->var(); | 386 Variable* variable = decl->proxy()->var(); |
| 361 VariableMode mode = decl->mode(); | 387 VariableMode mode = decl->mode(); |
| 362 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; | 388 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 environment()->Push(cache_array); | 705 environment()->Push(cache_array); |
| 680 environment()->Push(cache_length); | 706 environment()->Push(cache_length); |
| 681 environment()->Push(jsgraph()->ZeroConstant()); | 707 environment()->Push(jsgraph()->ZeroConstant()); |
| 682 // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 708 // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
| 683 LoopBuilder for_loop(this); | 709 LoopBuilder for_loop(this); |
| 684 for_loop.BeginLoop(); | 710 for_loop.BeginLoop(); |
| 685 // Check loop termination condition. | 711 // Check loop termination condition. |
| 686 Node* index = environment()->Peek(0); | 712 Node* index = environment()->Peek(0); |
| 687 Node* exit_cond = | 713 Node* exit_cond = |
| 688 NewNode(javascript()->LessThan(), index, cache_length); | 714 NewNode(javascript()->LessThan(), index, cache_length); |
| 715 // TODO(jarin): provide real bailout id. |
| 716 BuildLazyBailout(exit_cond, BailoutId::None()); |
| 689 for_loop.BreakUnless(exit_cond); | 717 for_loop.BreakUnless(exit_cond); |
| 690 // TODO(dcarney): this runtime call should be a handful of | 718 // TODO(dcarney): this runtime call should be a handful of |
| 691 // simplified instructions that | 719 // simplified instructions that |
| 692 // basically produce | 720 // basically produce |
| 693 // value = array[index] | 721 // value = array[index] |
| 694 environment()->Push(obj); | 722 environment()->Push(obj); |
| 695 environment()->Push(cache_array); | 723 environment()->Push(cache_array); |
| 696 environment()->Push(cache_type); | 724 environment()->Push(cache_type); |
| 697 environment()->Push(index); | 725 environment()->Push(index); |
| 698 Node* pair = | 726 Node* pair = |
| (...skipping 18 matching lines...) Expand all Loading... |
| 717 // Callee. | 745 // Callee. |
| 718 environment()->Push(jsgraph()->HeapConstant(function)); | 746 environment()->Push(jsgraph()->HeapConstant(function)); |
| 719 // Receiver. | 747 // Receiver. |
| 720 environment()->Push(obj); | 748 environment()->Push(obj); |
| 721 // Args. | 749 // Args. |
| 722 environment()->Push(value); | 750 environment()->Push(value); |
| 723 // result is either the string key or Smi(0) indicating the property | 751 // result is either the string key or Smi(0) indicating the property |
| 724 // is gone. | 752 // is gone. |
| 725 Node* res = ProcessArguments( | 753 Node* res = ProcessArguments( |
| 726 javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3); | 754 javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3); |
| 755 // TODO(jarin): provide real bailout id. |
| 756 BuildLazyBailout(res, BailoutId::None()); |
| 727 Node* property_missing = NewNode(javascript()->StrictEqual(), res, | 757 Node* property_missing = NewNode(javascript()->StrictEqual(), res, |
| 728 jsgraph()->ZeroConstant()); | 758 jsgraph()->ZeroConstant()); |
| 729 { | 759 { |
| 730 IfBuilder is_property_missing(this); | 760 IfBuilder is_property_missing(this); |
| 731 is_property_missing.If(property_missing); | 761 is_property_missing.If(property_missing); |
| 732 is_property_missing.Then(); | 762 is_property_missing.Then(); |
| 733 // Inc counter and continue. | 763 // Inc counter and continue. |
| 734 Node* index_inc = | 764 Node* index_inc = |
| 735 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | 765 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
| 736 environment()->Poke(0, index_inc); | 766 environment()->Poke(0, index_inc); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 compare_if.Then(); | 852 compare_if.Then(); |
| 823 Visit(expr->then_expression()); | 853 Visit(expr->then_expression()); |
| 824 compare_if.Else(); | 854 compare_if.Else(); |
| 825 Visit(expr->else_expression()); | 855 Visit(expr->else_expression()); |
| 826 compare_if.End(); | 856 compare_if.End(); |
| 827 ast_context()->ReplaceValue(); | 857 ast_context()->ReplaceValue(); |
| 828 } | 858 } |
| 829 | 859 |
| 830 | 860 |
| 831 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 861 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 832 Node* value = BuildVariableLoad(expr->var()); | 862 Node* value = BuildVariableLoad(expr->var(), expr->id()); |
| 833 ast_context()->ProduceValue(value); | 863 ast_context()->ProduceValue(value); |
| 834 } | 864 } |
| 835 | 865 |
| 836 | 866 |
| 837 void AstGraphBuilder::VisitLiteral(Literal* expr) { | 867 void AstGraphBuilder::VisitLiteral(Literal* expr) { |
| 838 Node* value = jsgraph()->Constant(expr->value()); | 868 Node* value = jsgraph()->Constant(expr->value()); |
| 839 ast_context()->ProduceValue(value); | 869 ast_context()->ProduceValue(value); |
| 840 } | 870 } |
| 841 | 871 |
| 842 | 872 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 919 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 890 // Fall through. | 920 // Fall through. |
| 891 case ObjectLiteral::Property::COMPUTED: { | 921 case ObjectLiteral::Property::COMPUTED: { |
| 892 // It is safe to use [[Put]] here because the boilerplate already | 922 // It is safe to use [[Put]] here because the boilerplate already |
| 893 // contains computed properties with an uninitialized value. | 923 // contains computed properties with an uninitialized value. |
| 894 if (key->value()->IsInternalizedString()) { | 924 if (key->value()->IsInternalizedString()) { |
| 895 if (property->emit_store()) { | 925 if (property->emit_store()) { |
| 896 VisitForValue(property->value()); | 926 VisitForValue(property->value()); |
| 897 Node* value = environment()->Pop(); | 927 Node* value = environment()->Pop(); |
| 898 PrintableUnique<Name> name = MakeUnique(key->AsPropertyName()); | 928 PrintableUnique<Name> name = MakeUnique(key->AsPropertyName()); |
| 899 NewNode(javascript()->StoreNamed(name), literal, value); | 929 Node* store = |
| 930 NewNode(javascript()->StoreNamed(name), literal, value); |
| 931 BuildLazyBailout(store, key->id()); |
| 900 } else { | 932 } else { |
| 901 VisitForEffect(property->value()); | 933 VisitForEffect(property->value()); |
| 902 } | 934 } |
| 903 break; | 935 break; |
| 904 } | 936 } |
| 905 environment()->Push(literal); // Duplicate receiver. | 937 environment()->Push(literal); // Duplicate receiver. |
| 906 VisitForValue(property->key()); | 938 VisitForValue(property->key()); |
| 907 VisitForValue(property->value()); | 939 VisitForValue(property->value()); |
| 908 Node* value = environment()->Pop(); | 940 Node* value = environment()->Pop(); |
| 909 Node* key = environment()->Pop(); | 941 Node* key = environment()->Pop(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 | 1012 |
| 981 // Create nodes to evaluate all the non-constant subexpressions and to store | 1013 // Create nodes to evaluate all the non-constant subexpressions and to store |
| 982 // them into the newly cloned array. | 1014 // them into the newly cloned array. |
| 983 for (int i = 0; i < expr->values()->length(); i++) { | 1015 for (int i = 0; i < expr->values()->length(); i++) { |
| 984 Expression* subexpr = expr->values()->at(i); | 1016 Expression* subexpr = expr->values()->at(i); |
| 985 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 1017 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 986 | 1018 |
| 987 VisitForValue(subexpr); | 1019 VisitForValue(subexpr); |
| 988 Node* value = environment()->Pop(); | 1020 Node* value = environment()->Pop(); |
| 989 Node* index = jsgraph()->Constant(i); | 1021 Node* index = jsgraph()->Constant(i); |
| 990 NewNode(javascript()->StoreProperty(), literal, index, value); | 1022 Node* store = NewNode(javascript()->StoreProperty(), literal, index, value); |
| 1023 BuildLazyBailout(store, expr->GetIdForElement(i)); |
| 991 } | 1024 } |
| 992 | 1025 |
| 993 environment()->Pop(); // Array literal index. | 1026 environment()->Pop(); // Array literal index. |
| 994 ast_context()->ProduceValue(environment()->Pop()); | 1027 ast_context()->ProduceValue(environment()->Pop()); |
| 995 } | 1028 } |
| 996 | 1029 |
| 997 | 1030 |
| 998 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) { | 1031 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) { |
| 999 DCHECK(expr->IsValidReferenceExpression()); | 1032 DCHECK(expr->IsValidReferenceExpression()); |
| 1000 | 1033 |
| 1001 // Left-hand side can only be a property, a global or a variable slot. | 1034 // Left-hand side can only be a property, a global or a variable slot. |
| 1002 Property* property = expr->AsProperty(); | 1035 Property* property = expr->AsProperty(); |
| 1003 LhsKind assign_type = DetermineLhsKind(expr); | 1036 LhsKind assign_type = DetermineLhsKind(expr); |
| 1004 | 1037 |
| 1005 // Evaluate LHS expression and store the value. | 1038 // Evaluate LHS expression and store the value. |
| 1006 switch (assign_type) { | 1039 switch (assign_type) { |
| 1007 case VARIABLE: { | 1040 case VARIABLE: { |
| 1008 Variable* var = expr->AsVariableProxy()->var(); | 1041 Variable* var = expr->AsVariableProxy()->var(); |
| 1009 BuildVariableAssignment(var, value, Token::ASSIGN); | 1042 // TODO(jarin) Fill in the correct bailout id. |
| 1043 BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None()); |
| 1010 break; | 1044 break; |
| 1011 } | 1045 } |
| 1012 case NAMED_PROPERTY: { | 1046 case NAMED_PROPERTY: { |
| 1013 environment()->Push(value); | 1047 environment()->Push(value); |
| 1014 VisitForValue(property->obj()); | 1048 VisitForValue(property->obj()); |
| 1015 Node* object = environment()->Pop(); | 1049 Node* object = environment()->Pop(); |
| 1016 value = environment()->Pop(); | 1050 value = environment()->Pop(); |
| 1017 PrintableUnique<Name> name = | 1051 PrintableUnique<Name> name = |
| 1018 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1052 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
| 1019 NewNode(javascript()->StoreNamed(name), object, value); | 1053 Node* store = NewNode(javascript()->StoreNamed(name), object, value); |
| 1054 // TODO(jarin) Fill in the correct bailout id. |
| 1055 BuildLazyBailout(store, BailoutId::None()); |
| 1020 break; | 1056 break; |
| 1021 } | 1057 } |
| 1022 case KEYED_PROPERTY: { | 1058 case KEYED_PROPERTY: { |
| 1023 environment()->Push(value); | 1059 environment()->Push(value); |
| 1024 VisitForValue(property->obj()); | 1060 VisitForValue(property->obj()); |
| 1025 VisitForValue(property->key()); | 1061 VisitForValue(property->key()); |
| 1026 Node* key = environment()->Pop(); | 1062 Node* key = environment()->Pop(); |
| 1027 Node* object = environment()->Pop(); | 1063 Node* object = environment()->Pop(); |
| 1028 value = environment()->Pop(); | 1064 value = environment()->Pop(); |
| 1029 NewNode(javascript()->StoreProperty(), object, key, value); | 1065 Node* store = NewNode(javascript()->StoreProperty(), object, key, value); |
| 1066 // TODO(jarin) Fill in the correct bailout id. |
| 1067 BuildLazyBailout(store, BailoutId::None()); |
| 1030 break; | 1068 break; |
| 1031 } | 1069 } |
| 1032 } | 1070 } |
| 1033 } | 1071 } |
| 1034 | 1072 |
| 1035 | 1073 |
| 1036 void AstGraphBuilder::VisitAssignment(Assignment* expr) { | 1074 void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
| 1037 DCHECK(expr->target()->IsValidReferenceExpression()); | 1075 DCHECK(expr->target()->IsValidReferenceExpression()); |
| 1038 | 1076 |
| 1039 // Left-hand side can only be a property, a global or a variable slot. | 1077 // Left-hand side can only be a property, a global or a variable slot. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1055 } | 1093 } |
| 1056 } | 1094 } |
| 1057 | 1095 |
| 1058 // Evaluate the value and potentially handle compound assignments by loading | 1096 // Evaluate the value and potentially handle compound assignments by loading |
| 1059 // the left-hand side value and performing a binary operation. | 1097 // the left-hand side value and performing a binary operation. |
| 1060 if (expr->is_compound()) { | 1098 if (expr->is_compound()) { |
| 1061 Node* old_value = NULL; | 1099 Node* old_value = NULL; |
| 1062 switch (assign_type) { | 1100 switch (assign_type) { |
| 1063 case VARIABLE: { | 1101 case VARIABLE: { |
| 1064 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1102 Variable* variable = expr->target()->AsVariableProxy()->var(); |
| 1065 old_value = BuildVariableLoad(variable); | 1103 old_value = BuildVariableLoad(variable, expr->target()->id()); |
| 1066 break; | 1104 break; |
| 1067 } | 1105 } |
| 1068 case NAMED_PROPERTY: { | 1106 case NAMED_PROPERTY: { |
| 1069 Node* object = environment()->Top(); | 1107 Node* object = environment()->Top(); |
| 1070 PrintableUnique<Name> name = | 1108 PrintableUnique<Name> name = |
| 1071 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1109 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
| 1072 old_value = NewNode(javascript()->LoadNamed(name), object); | 1110 old_value = NewNode(javascript()->LoadNamed(name), object); |
| 1111 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
| 1073 break; | 1112 break; |
| 1074 } | 1113 } |
| 1075 case KEYED_PROPERTY: { | 1114 case KEYED_PROPERTY: { |
| 1076 Node* key = environment()->Top(); | 1115 Node* key = environment()->Top(); |
| 1077 Node* object = environment()->Peek(1); | 1116 Node* object = environment()->Peek(1); |
| 1078 old_value = NewNode(javascript()->LoadProperty(), object, key); | 1117 old_value = NewNode(javascript()->LoadProperty(), object, key); |
| 1118 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
| 1079 break; | 1119 break; |
| 1080 } | 1120 } |
| 1081 } | 1121 } |
| 1082 environment()->Push(old_value); | 1122 environment()->Push(old_value); |
| 1083 VisitForValue(expr->value()); | 1123 VisitForValue(expr->value()); |
| 1084 Node* right = environment()->Pop(); | 1124 Node* right = environment()->Pop(); |
| 1085 Node* left = environment()->Pop(); | 1125 Node* left = environment()->Pop(); |
| 1086 Node* value = BuildBinaryOp(left, right, expr->binary_op()); | 1126 Node* value = BuildBinaryOp(left, right, expr->binary_op()); |
| 1087 environment()->Push(value); | 1127 environment()->Push(value); |
| 1128 BuildLazyBailout(value, expr->binary_operation()->id()); |
| 1088 } else { | 1129 } else { |
| 1089 VisitForValue(expr->value()); | 1130 VisitForValue(expr->value()); |
| 1090 } | 1131 } |
| 1091 | 1132 |
| 1092 // Store the value. | 1133 // Store the value. |
| 1093 Node* value = environment()->Pop(); | 1134 Node* value = environment()->Pop(); |
| 1094 switch (assign_type) { | 1135 switch (assign_type) { |
| 1095 case VARIABLE: { | 1136 case VARIABLE: { |
| 1096 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1137 Variable* variable = expr->target()->AsVariableProxy()->var(); |
| 1097 BuildVariableAssignment(variable, value, expr->op()); | 1138 BuildVariableAssignment(variable, value, expr->op(), |
| 1139 expr->AssignmentId()); |
| 1098 break; | 1140 break; |
| 1099 } | 1141 } |
| 1100 case NAMED_PROPERTY: { | 1142 case NAMED_PROPERTY: { |
| 1101 Node* object = environment()->Pop(); | 1143 Node* object = environment()->Pop(); |
| 1102 PrintableUnique<Name> name = | 1144 PrintableUnique<Name> name = |
| 1103 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1145 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
| 1104 NewNode(javascript()->StoreNamed(name), object, value); | 1146 Node* store = NewNode(javascript()->StoreNamed(name), object, value); |
| 1147 BuildLazyBailout(store, expr->AssignmentId()); |
| 1105 break; | 1148 break; |
| 1106 } | 1149 } |
| 1107 case KEYED_PROPERTY: { | 1150 case KEYED_PROPERTY: { |
| 1108 Node* key = environment()->Pop(); | 1151 Node* key = environment()->Pop(); |
| 1109 Node* object = environment()->Pop(); | 1152 Node* object = environment()->Pop(); |
| 1110 NewNode(javascript()->StoreProperty(), object, key, value); | 1153 Node* store = NewNode(javascript()->StoreProperty(), object, key, value); |
| 1154 BuildLazyBailout(store, expr->AssignmentId()); |
| 1111 break; | 1155 break; |
| 1112 } | 1156 } |
| 1113 } | 1157 } |
| 1114 | 1158 |
| 1115 ast_context()->ProduceValue(value); | 1159 ast_context()->ProduceValue(value); |
| 1116 } | 1160 } |
| 1117 | 1161 |
| 1118 | 1162 |
| 1119 void AstGraphBuilder::VisitYield(Yield* expr) { | 1163 void AstGraphBuilder::VisitYield(Yield* expr) { |
| 1120 VisitForValue(expr->generator_object()); | 1164 VisitForValue(expr->generator_object()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1143 PrintableUnique<Name> name = | 1187 PrintableUnique<Name> name = |
| 1144 MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); | 1188 MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); |
| 1145 value = NewNode(javascript()->LoadNamed(name), object); | 1189 value = NewNode(javascript()->LoadNamed(name), object); |
| 1146 } else { | 1190 } else { |
| 1147 VisitForValue(expr->obj()); | 1191 VisitForValue(expr->obj()); |
| 1148 VisitForValue(expr->key()); | 1192 VisitForValue(expr->key()); |
| 1149 Node* key = environment()->Pop(); | 1193 Node* key = environment()->Pop(); |
| 1150 Node* object = environment()->Pop(); | 1194 Node* object = environment()->Pop(); |
| 1151 value = NewNode(javascript()->LoadProperty(), object, key); | 1195 value = NewNode(javascript()->LoadProperty(), object, key); |
| 1152 } | 1196 } |
| 1153 ast_context()->ProduceValue(value); | 1197 ast_context()->ProduceValueWithLazyBailout(value); |
| 1154 } | 1198 } |
| 1155 | 1199 |
| 1156 | 1200 |
| 1157 void AstGraphBuilder::VisitCall(Call* expr) { | 1201 void AstGraphBuilder::VisitCall(Call* expr) { |
| 1158 Expression* callee = expr->expression(); | 1202 Expression* callee = expr->expression(); |
| 1159 Call::CallType call_type = expr->GetCallType(isolate()); | 1203 Call::CallType call_type = expr->GetCallType(isolate()); |
| 1160 | 1204 |
| 1161 // Prepare the callee and the receiver to the function call. This depends on | 1205 // Prepare the callee and the receiver to the function call. This depends on |
| 1162 // the semantics of the underlying call type. | 1206 // the semantics of the underlying call type. |
| 1163 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; | 1207 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
| 1164 Node* receiver_value = NULL; | 1208 Node* receiver_value = NULL; |
| 1165 Node* callee_value = NULL; | 1209 Node* callee_value = NULL; |
| 1166 bool possibly_eval = false; | 1210 bool possibly_eval = false; |
| 1167 switch (call_type) { | 1211 switch (call_type) { |
| 1168 case Call::GLOBAL_CALL: { | 1212 case Call::GLOBAL_CALL: { |
| 1169 Variable* variable = callee->AsVariableProxy()->var(); | 1213 Variable* variable = callee->AsVariableProxy()->var(); |
| 1170 callee_value = BuildVariableLoad(variable); | 1214 callee_value = BuildVariableLoad(variable, expr->expression()->id()); |
| 1171 receiver_value = jsgraph()->UndefinedConstant(); | 1215 receiver_value = jsgraph()->UndefinedConstant(); |
| 1172 break; | 1216 break; |
| 1173 } | 1217 } |
| 1174 case Call::LOOKUP_SLOT_CALL: { | 1218 case Call::LOOKUP_SLOT_CALL: { |
| 1175 Variable* variable = callee->AsVariableProxy()->var(); | 1219 Variable* variable = callee->AsVariableProxy()->var(); |
| 1176 DCHECK(variable->location() == Variable::LOOKUP); | 1220 DCHECK(variable->location() == Variable::LOOKUP); |
| 1177 Node* name = jsgraph()->Constant(variable->name()); | 1221 Node* name = jsgraph()->Constant(variable->name()); |
| 1178 Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); | 1222 Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); |
| 1179 Node* pair = NewNode(op, current_context(), name); | 1223 Node* pair = NewNode(op, current_context(), name); |
| 1180 callee_value = NewNode(common()->Projection(0), pair); | 1224 callee_value = NewNode(common()->Projection(0), pair); |
| 1181 receiver_value = NewNode(common()->Projection(1), pair); | 1225 receiver_value = NewNode(common()->Projection(1), pair); |
| 1182 break; | 1226 break; |
| 1183 } | 1227 } |
| 1184 case Call::PROPERTY_CALL: { | 1228 case Call::PROPERTY_CALL: { |
| 1185 Property* property = callee->AsProperty(); | 1229 Property* property = callee->AsProperty(); |
| 1186 VisitForValue(property->obj()); | 1230 VisitForValue(property->obj()); |
| 1187 Node* object = environment()->Top(); | 1231 Node* object = environment()->Top(); |
| 1188 if (property->key()->IsPropertyName()) { | 1232 if (property->key()->IsPropertyName()) { |
| 1189 PrintableUnique<Name> name = | 1233 PrintableUnique<Name> name = |
| 1190 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1234 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
| 1191 callee_value = NewNode(javascript()->LoadNamed(name), object); | 1235 callee_value = NewNode(javascript()->LoadNamed(name), object); |
| 1192 } else { | 1236 } else { |
| 1193 VisitForValue(property->key()); | 1237 VisitForValue(property->key()); |
| 1194 Node* key = environment()->Pop(); | 1238 Node* key = environment()->Pop(); |
| 1195 callee_value = NewNode(javascript()->LoadProperty(), object, key); | 1239 callee_value = NewNode(javascript()->LoadProperty(), object, key); |
| 1196 } | 1240 } |
| 1241 BuildLazyBailoutWithPushedNode(callee_value, property->LoadId()); |
| 1197 receiver_value = environment()->Pop(); | 1242 receiver_value = environment()->Pop(); |
| 1198 // Note that a PROPERTY_CALL requires the receiver to be wrapped into an | 1243 // Note that a PROPERTY_CALL requires the receiver to be wrapped into an |
| 1199 // object for sloppy callees. This could also be modeled explicitly here, | 1244 // object for sloppy callees. This could also be modeled explicitly here, |
| 1200 // thereby obsoleting the need for a flag to the call operator. | 1245 // thereby obsoleting the need for a flag to the call operator. |
| 1201 flags = CALL_AS_METHOD; | 1246 flags = CALL_AS_METHOD; |
| 1202 break; | 1247 break; |
| 1203 } | 1248 } |
| 1204 case Call::POSSIBLY_EVAL_CALL: | 1249 case Call::POSSIBLY_EVAL_CALL: |
| 1205 possibly_eval = true; | 1250 possibly_eval = true; |
| 1206 // Fall through. | 1251 // Fall through. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 Node* new_receiver = NewNode(common()->Projection(1), pair); | 1286 Node* new_receiver = NewNode(common()->Projection(1), pair); |
| 1242 | 1287 |
| 1243 // Patch callee and receiver on the environment. | 1288 // Patch callee and receiver on the environment. |
| 1244 environment()->Poke(arg_count + 1, new_callee); | 1289 environment()->Poke(arg_count + 1, new_callee); |
| 1245 environment()->Poke(arg_count + 0, new_receiver); | 1290 environment()->Poke(arg_count + 0, new_receiver); |
| 1246 } | 1291 } |
| 1247 | 1292 |
| 1248 // Create node to perform the function call. | 1293 // Create node to perform the function call. |
| 1249 Operator* call = javascript()->Call(args->length() + 2, flags); | 1294 Operator* call = javascript()->Call(args->length() + 2, flags); |
| 1250 Node* value = ProcessArguments(call, args->length() + 2); | 1295 Node* value = ProcessArguments(call, args->length() + 2); |
| 1251 ast_context()->ProduceValue(value); | 1296 ast_context()->ProduceValueWithLazyBailout(value); |
| 1252 } | 1297 } |
| 1253 | 1298 |
| 1254 | 1299 |
| 1255 void AstGraphBuilder::VisitCallNew(CallNew* expr) { | 1300 void AstGraphBuilder::VisitCallNew(CallNew* expr) { |
| 1256 VisitForValue(expr->expression()); | 1301 VisitForValue(expr->expression()); |
| 1257 | 1302 |
| 1258 // Evaluate all arguments to the construct call. | 1303 // Evaluate all arguments to the construct call. |
| 1259 ZoneList<Expression*>* args = expr->arguments(); | 1304 ZoneList<Expression*>* args = expr->arguments(); |
| 1260 VisitForValues(args); | 1305 VisitForValues(args); |
| 1261 | 1306 |
| 1262 // Create node to perform the construct call. | 1307 // Create node to perform the construct call. |
| 1263 Operator* call = javascript()->CallNew(args->length() + 1); | 1308 Operator* call = javascript()->CallNew(args->length() + 1); |
| 1264 Node* value = ProcessArguments(call, args->length() + 1); | 1309 Node* value = ProcessArguments(call, args->length() + 1); |
| 1265 ast_context()->ProduceValue(value); | 1310 ast_context()->ProduceValueWithLazyBailout(value); |
| 1266 } | 1311 } |
| 1267 | 1312 |
| 1268 | 1313 |
| 1269 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { | 1314 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { |
| 1270 Handle<String> name = expr->name(); | 1315 Handle<String> name = expr->name(); |
| 1271 | 1316 |
| 1272 // The callee and the receiver both have to be pushed onto the operand stack | 1317 // The callee and the receiver both have to be pushed onto the operand stack |
| 1273 // before arguments are being evaluated. | 1318 // before arguments are being evaluated. |
| 1274 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; | 1319 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
| 1275 Node* receiver_value = BuildLoadBuiltinsObject(); | 1320 Node* receiver_value = BuildLoadBuiltinsObject(); |
| 1276 PrintableUnique<String> unique = MakeUnique(name); | 1321 PrintableUnique<String> unique = MakeUnique(name); |
| 1277 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); | 1322 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); |
| 1278 environment()->Push(callee_value); | 1323 environment()->Push(callee_value); |
| 1324 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft |
| 1325 // refuses to optimize functions with jsruntime calls). |
| 1326 BuildLazyBailout(callee_value, BailoutId::None()); |
| 1279 environment()->Push(receiver_value); | 1327 environment()->Push(receiver_value); |
| 1280 | 1328 |
| 1281 // Evaluate all arguments to the JS runtime call. | 1329 // Evaluate all arguments to the JS runtime call. |
| 1282 ZoneList<Expression*>* args = expr->arguments(); | 1330 ZoneList<Expression*>* args = expr->arguments(); |
| 1283 VisitForValues(args); | 1331 VisitForValues(args); |
| 1284 | 1332 |
| 1285 // Create node to perform the JS runtime call. | 1333 // Create node to perform the JS runtime call. |
| 1286 Operator* call = javascript()->Call(args->length() + 2, flags); | 1334 Operator* call = javascript()->Call(args->length() + 2, flags); |
| 1287 Node* value = ProcessArguments(call, args->length() + 2); | 1335 Node* value = ProcessArguments(call, args->length() + 2); |
| 1288 ast_context()->ProduceValue(value); | 1336 ast_context()->ProduceValueWithLazyBailout(value); |
| 1289 } | 1337 } |
| 1290 | 1338 |
| 1291 | 1339 |
| 1292 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 1340 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 1293 const Runtime::Function* function = expr->function(); | 1341 const Runtime::Function* function = expr->function(); |
| 1294 | 1342 |
| 1295 // Handle calls to runtime functions implemented in JavaScript separately as | 1343 // Handle calls to runtime functions implemented in JavaScript separately as |
| 1296 // the call follows JavaScript ABI and the callee is statically unknown. | 1344 // the call follows JavaScript ABI and the callee is statically unknown. |
| 1297 if (expr->is_jsruntime()) { | 1345 if (expr->is_jsruntime()) { |
| 1298 DCHECK(function == NULL && expr->name()->length() > 0); | 1346 DCHECK(function == NULL && expr->name()->length() > 0); |
| 1299 return VisitCallJSRuntime(expr); | 1347 return VisitCallJSRuntime(expr); |
| 1300 } | 1348 } |
| 1301 | 1349 |
| 1302 // Evaluate all arguments to the runtime call. | 1350 // Evaluate all arguments to the runtime call. |
| 1303 ZoneList<Expression*>* args = expr->arguments(); | 1351 ZoneList<Expression*>* args = expr->arguments(); |
| 1304 VisitForValues(args); | 1352 VisitForValues(args); |
| 1305 | 1353 |
| 1306 // Create node to perform the runtime call. | 1354 // Create node to perform the runtime call. |
| 1307 Runtime::FunctionId functionId = function->function_id; | 1355 Runtime::FunctionId functionId = function->function_id; |
| 1308 Operator* call = javascript()->Runtime(functionId, args->length()); | 1356 Operator* call = javascript()->Runtime(functionId, args->length()); |
| 1309 Node* value = ProcessArguments(call, args->length()); | 1357 Node* value = ProcessArguments(call, args->length()); |
| 1310 ast_context()->ProduceValue(value); | 1358 ast_context()->ProduceValueWithLazyBailout(value); |
| 1311 | |
| 1312 BuildLazyBailout(value, expr->id()); | |
| 1313 } | 1359 } |
| 1314 | 1360 |
| 1315 | 1361 |
| 1316 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 1362 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 1317 switch (expr->op()) { | 1363 switch (expr->op()) { |
| 1318 case Token::DELETE: | 1364 case Token::DELETE: |
| 1319 return VisitDelete(expr); | 1365 return VisitDelete(expr); |
| 1320 case Token::VOID: | 1366 case Token::VOID: |
| 1321 return VisitVoid(expr); | 1367 return VisitVoid(expr); |
| 1322 case Token::TYPEOF: | 1368 case Token::TYPEOF: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1339 // Reserve space for result of postfix operation. | 1385 // Reserve space for result of postfix operation. |
| 1340 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect(); | 1386 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect(); |
| 1341 if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant()); | 1387 if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant()); |
| 1342 | 1388 |
| 1343 // Evaluate LHS expression and get old value. | 1389 // Evaluate LHS expression and get old value. |
| 1344 Node* old_value = NULL; | 1390 Node* old_value = NULL; |
| 1345 int stack_depth = -1; | 1391 int stack_depth = -1; |
| 1346 switch (assign_type) { | 1392 switch (assign_type) { |
| 1347 case VARIABLE: { | 1393 case VARIABLE: { |
| 1348 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 1394 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| 1349 old_value = BuildVariableLoad(variable); | 1395 old_value = BuildVariableLoad(variable, expr->expression()->id()); |
| 1350 stack_depth = 0; | 1396 stack_depth = 0; |
| 1351 break; | 1397 break; |
| 1352 } | 1398 } |
| 1353 case NAMED_PROPERTY: { | 1399 case NAMED_PROPERTY: { |
| 1354 VisitForValue(property->obj()); | 1400 VisitForValue(property->obj()); |
| 1355 Node* object = environment()->Top(); | 1401 Node* object = environment()->Top(); |
| 1356 PrintableUnique<Name> name = | 1402 PrintableUnique<Name> name = |
| 1357 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1403 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
| 1358 old_value = NewNode(javascript()->LoadNamed(name), object); | 1404 old_value = NewNode(javascript()->LoadNamed(name), object); |
| 1405 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
| 1359 stack_depth = 1; | 1406 stack_depth = 1; |
| 1360 break; | 1407 break; |
| 1361 } | 1408 } |
| 1362 case KEYED_PROPERTY: { | 1409 case KEYED_PROPERTY: { |
| 1363 VisitForValue(property->obj()); | 1410 VisitForValue(property->obj()); |
| 1364 VisitForValue(property->key()); | 1411 VisitForValue(property->key()); |
| 1365 Node* key = environment()->Top(); | 1412 Node* key = environment()->Top(); |
| 1366 Node* object = environment()->Peek(1); | 1413 Node* object = environment()->Peek(1); |
| 1367 old_value = NewNode(javascript()->LoadProperty(), object, key); | 1414 old_value = NewNode(javascript()->LoadProperty(), object, key); |
| 1415 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
| 1368 stack_depth = 2; | 1416 stack_depth = 2; |
| 1369 break; | 1417 break; |
| 1370 } | 1418 } |
| 1371 } | 1419 } |
| 1372 | 1420 |
| 1373 // Convert old value into a number. | 1421 // Convert old value into a number. |
| 1374 old_value = NewNode(javascript()->ToNumber(), old_value); | 1422 old_value = NewNode(javascript()->ToNumber(), old_value); |
| 1375 | 1423 |
| 1376 // Save result for postfix expressions at correct stack depth. | 1424 // Save result for postfix expressions at correct stack depth. |
| 1377 if (is_postfix) environment()->Poke(stack_depth, old_value); | 1425 if (is_postfix) environment()->Poke(stack_depth, old_value); |
| 1378 | 1426 |
| 1379 // Create node to perform +1/-1 operation. | 1427 // Create node to perform +1/-1 operation. |
| 1380 Node* value = | 1428 Node* value = |
| 1381 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); | 1429 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); |
| 1430 // TODO(jarin) Insert proper bailout id here (will need to change |
| 1431 // full code generator). |
| 1432 BuildLazyBailout(value, BailoutId::None()); |
| 1382 | 1433 |
| 1383 // Store the value. | 1434 // Store the value. |
| 1384 switch (assign_type) { | 1435 switch (assign_type) { |
| 1385 case VARIABLE: { | 1436 case VARIABLE: { |
| 1386 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 1437 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| 1387 BuildVariableAssignment(variable, value, expr->op()); | 1438 BuildVariableAssignment(variable, value, expr->op(), |
| 1439 expr->AssignmentId()); |
| 1388 break; | 1440 break; |
| 1389 } | 1441 } |
| 1390 case NAMED_PROPERTY: { | 1442 case NAMED_PROPERTY: { |
| 1391 Node* object = environment()->Pop(); | 1443 Node* object = environment()->Pop(); |
| 1392 PrintableUnique<Name> name = | 1444 PrintableUnique<Name> name = |
| 1393 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1445 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
| 1394 NewNode(javascript()->StoreNamed(name), object, value); | 1446 Node* store = NewNode(javascript()->StoreNamed(name), object, value); |
| 1447 BuildLazyBailout(store, expr->AssignmentId()); |
| 1395 break; | 1448 break; |
| 1396 } | 1449 } |
| 1397 case KEYED_PROPERTY: { | 1450 case KEYED_PROPERTY: { |
| 1398 Node* key = environment()->Pop(); | 1451 Node* key = environment()->Pop(); |
| 1399 Node* object = environment()->Pop(); | 1452 Node* object = environment()->Pop(); |
| 1400 NewNode(javascript()->StoreProperty(), object, key, value); | 1453 Node* store = NewNode(javascript()->StoreProperty(), object, key, value); |
| 1454 BuildLazyBailout(store, expr->AssignmentId()); |
| 1401 break; | 1455 break; |
| 1402 } | 1456 } |
| 1403 } | 1457 } |
| 1404 | 1458 |
| 1405 // Restore old value for postfix expressions. | 1459 // Restore old value for postfix expressions. |
| 1406 if (is_postfix) value = environment()->Pop(); | 1460 if (is_postfix) value = environment()->Pop(); |
| 1407 | 1461 |
| 1408 ast_context()->ProduceValue(value); | 1462 ast_context()->ProduceValue(value); |
| 1409 } | 1463 } |
| 1410 | 1464 |
| 1411 | 1465 |
| 1412 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 1466 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| 1413 switch (expr->op()) { | 1467 switch (expr->op()) { |
| 1414 case Token::COMMA: | 1468 case Token::COMMA: |
| 1415 return VisitComma(expr); | 1469 return VisitComma(expr); |
| 1416 case Token::OR: | 1470 case Token::OR: |
| 1417 case Token::AND: | 1471 case Token::AND: |
| 1418 return VisitLogicalExpression(expr); | 1472 return VisitLogicalExpression(expr); |
| 1419 default: { | 1473 default: { |
| 1420 VisitForValue(expr->left()); | 1474 VisitForValue(expr->left()); |
| 1421 VisitForValue(expr->right()); | 1475 VisitForValue(expr->right()); |
| 1422 Node* right = environment()->Pop(); | 1476 Node* right = environment()->Pop(); |
| 1423 Node* left = environment()->Pop(); | 1477 Node* left = environment()->Pop(); |
| 1424 Node* value = BuildBinaryOp(left, right, expr->op()); | 1478 Node* value = BuildBinaryOp(left, right, expr->op()); |
| 1425 ast_context()->ProduceValue(value); | 1479 ast_context()->ProduceValueWithLazyBailout(value); |
| 1426 } | 1480 } |
| 1427 } | 1481 } |
| 1428 } | 1482 } |
| 1429 | 1483 |
| 1430 | 1484 |
| 1431 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 1485 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 1432 Operator* op; | 1486 Operator* op; |
| 1433 switch (expr->op()) { | 1487 switch (expr->op()) { |
| 1434 case Token::EQ: | 1488 case Token::EQ: |
| 1435 op = javascript()->Equal(); | 1489 op = javascript()->Equal(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1464 default: | 1518 default: |
| 1465 op = NULL; | 1519 op = NULL; |
| 1466 UNREACHABLE(); | 1520 UNREACHABLE(); |
| 1467 } | 1521 } |
| 1468 VisitForValue(expr->left()); | 1522 VisitForValue(expr->left()); |
| 1469 VisitForValue(expr->right()); | 1523 VisitForValue(expr->right()); |
| 1470 Node* right = environment()->Pop(); | 1524 Node* right = environment()->Pop(); |
| 1471 Node* left = environment()->Pop(); | 1525 Node* left = environment()->Pop(); |
| 1472 Node* value = NewNode(op, left, right); | 1526 Node* value = NewNode(op, left, right); |
| 1473 ast_context()->ProduceValue(value); | 1527 ast_context()->ProduceValue(value); |
| 1528 |
| 1529 BuildLazyBailout(value, expr->id()); |
| 1474 } | 1530 } |
| 1475 | 1531 |
| 1476 | 1532 |
| 1477 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 1533 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 1478 Node* value = GetFunctionClosure(); | 1534 Node* value = GetFunctionClosure(); |
| 1479 ast_context()->ProduceValue(value); | 1535 ast_context()->ProduceValue(value); |
| 1480 } | 1536 } |
| 1481 | 1537 |
| 1482 | 1538 |
| 1483 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); } | 1539 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1543 ast_context()->ProduceValue(value); | 1599 ast_context()->ProduceValue(value); |
| 1544 } | 1600 } |
| 1545 | 1601 |
| 1546 | 1602 |
| 1547 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 1603 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
| 1548 Node* operand; | 1604 Node* operand; |
| 1549 if (expr->expression()->IsVariableProxy()) { | 1605 if (expr->expression()->IsVariableProxy()) { |
| 1550 // Typeof does not throw a reference error on global variables, hence we | 1606 // Typeof does not throw a reference error on global variables, hence we |
| 1551 // perform a non-contextual load in case the operand is a variable proxy. | 1607 // perform a non-contextual load in case the operand is a variable proxy. |
| 1552 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 1608 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| 1553 operand = BuildVariableLoad(variable, NOT_CONTEXTUAL); | 1609 operand = |
| 1610 BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL); |
| 1554 } else { | 1611 } else { |
| 1555 VisitForValue(expr->expression()); | 1612 VisitForValue(expr->expression()); |
| 1556 operand = environment()->Pop(); | 1613 operand = environment()->Pop(); |
| 1557 } | 1614 } |
| 1558 Node* value = NewNode(javascript()->TypeOf(), operand); | 1615 Node* value = NewNode(javascript()->TypeOf(), operand); |
| 1559 ast_context()->ProduceValue(value); | 1616 ast_context()->ProduceValue(value); |
| 1560 } | 1617 } |
| 1561 | 1618 |
| 1562 | 1619 |
| 1563 void AstGraphBuilder::VisitNot(UnaryOperation* expr) { | 1620 void AstGraphBuilder::VisitNot(UnaryOperation* expr) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { | 1700 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { |
| 1644 if (arguments == NULL) return NULL; | 1701 if (arguments == NULL) return NULL; |
| 1645 | 1702 |
| 1646 // Allocate and initialize a new arguments object. | 1703 // Allocate and initialize a new arguments object. |
| 1647 Node* callee = GetFunctionClosure(); | 1704 Node* callee = GetFunctionClosure(); |
| 1648 Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); | 1705 Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); |
| 1649 Node* object = NewNode(op, callee); | 1706 Node* object = NewNode(op, callee); |
| 1650 | 1707 |
| 1651 // Assign the object to the arguments variable. | 1708 // Assign the object to the arguments variable. |
| 1652 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); | 1709 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
| 1653 BuildVariableAssignment(arguments, object, Token::ASSIGN); | 1710 // This should never lazy deopt, so it is fine to send invalid bailout id. |
| 1711 BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None()); |
| 1654 | 1712 |
| 1655 return object; | 1713 return object; |
| 1656 } | 1714 } |
| 1657 | 1715 |
| 1658 | 1716 |
| 1659 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, | 1717 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, |
| 1660 Node* not_hole) { | 1718 Node* not_hole) { |
| 1661 IfBuilder hole_check(this); | 1719 IfBuilder hole_check(this); |
| 1662 Node* the_hole = jsgraph()->TheHoleConstant(); | 1720 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 1663 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); | 1721 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1680 hole_check.Then(); | 1738 hole_check.Then(); |
| 1681 environment()->Push(BuildThrowReferenceError(variable)); | 1739 environment()->Push(BuildThrowReferenceError(variable)); |
| 1682 hole_check.Else(); | 1740 hole_check.Else(); |
| 1683 environment()->Push(not_hole); | 1741 environment()->Push(not_hole); |
| 1684 hole_check.End(); | 1742 hole_check.End(); |
| 1685 return environment()->Pop(); | 1743 return environment()->Pop(); |
| 1686 } | 1744 } |
| 1687 | 1745 |
| 1688 | 1746 |
| 1689 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, | 1747 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
| 1748 BailoutId bailout_id, |
| 1690 ContextualMode contextual_mode) { | 1749 ContextualMode contextual_mode) { |
| 1691 Node* the_hole = jsgraph()->TheHoleConstant(); | 1750 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 1692 VariableMode mode = variable->mode(); | 1751 VariableMode mode = variable->mode(); |
| 1693 switch (variable->location()) { | 1752 switch (variable->location()) { |
| 1694 case Variable::UNALLOCATED: { | 1753 case Variable::UNALLOCATED: { |
| 1695 // Global var, const, or let variable. | 1754 // Global var, const, or let variable. |
| 1696 Node* global = BuildLoadGlobalObject(); | 1755 Node* global = BuildLoadGlobalObject(); |
| 1697 PrintableUnique<Name> name = MakeUnique(variable->name()); | 1756 PrintableUnique<Name> name = MakeUnique(variable->name()); |
| 1698 Operator* op = javascript()->LoadNamed(name, contextual_mode); | 1757 Operator* op = javascript()->LoadNamed(name, contextual_mode); |
| 1699 return NewNode(op, global); | 1758 Node* node = NewNode(op, global); |
| 1759 BuildLazyBailoutWithPushedNode(node, bailout_id); |
| 1760 return node; |
| 1700 } | 1761 } |
| 1701 case Variable::PARAMETER: | 1762 case Variable::PARAMETER: |
| 1702 case Variable::LOCAL: { | 1763 case Variable::LOCAL: { |
| 1703 // Local var, const, or let variable. | 1764 // Local var, const, or let variable. |
| 1704 Node* value = environment()->Lookup(variable); | 1765 Node* value = environment()->Lookup(variable); |
| 1705 if (mode == CONST_LEGACY) { | 1766 if (mode == CONST_LEGACY) { |
| 1706 // Perform check for uninitialized legacy const variables. | 1767 // Perform check for uninitialized legacy const variables. |
| 1707 if (value->op() == the_hole->op()) { | 1768 if (value->op() == the_hole->op()) { |
| 1708 value = jsgraph()->UndefinedConstant(); | 1769 value = jsgraph()->UndefinedConstant(); |
| 1709 } else if (value->opcode() == IrOpcode::kPhi) { | 1770 } else if (value->opcode() == IrOpcode::kPhi) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1778 Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); | 1839 Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); |
| 1779 return NewNode(op, current_context(), name); | 1840 return NewNode(op, current_context(), name); |
| 1780 } | 1841 } |
| 1781 } | 1842 } |
| 1782 UNREACHABLE(); | 1843 UNREACHABLE(); |
| 1783 return NULL; | 1844 return NULL; |
| 1784 } | 1845 } |
| 1785 | 1846 |
| 1786 | 1847 |
| 1787 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, | 1848 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, |
| 1788 Token::Value op) { | 1849 Token::Value op, |
| 1850 BailoutId bailout_id) { |
| 1789 Node* the_hole = jsgraph()->TheHoleConstant(); | 1851 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 1790 VariableMode mode = variable->mode(); | 1852 VariableMode mode = variable->mode(); |
| 1791 switch (variable->location()) { | 1853 switch (variable->location()) { |
| 1792 case Variable::UNALLOCATED: { | 1854 case Variable::UNALLOCATED: { |
| 1793 // Global var, const, or let variable. | 1855 // Global var, const, or let variable. |
| 1794 Node* global = BuildLoadGlobalObject(); | 1856 Node* global = BuildLoadGlobalObject(); |
| 1795 PrintableUnique<Name> name = MakeUnique(variable->name()); | 1857 PrintableUnique<Name> name = MakeUnique(variable->name()); |
| 1796 Operator* op = javascript()->StoreNamed(name); | 1858 Operator* op = javascript()->StoreNamed(name); |
| 1797 return NewNode(op, global, value); | 1859 Node* store = NewNode(op, global, value); |
| 1860 BuildLazyBailout(store, bailout_id); |
| 1861 return store; |
| 1798 } | 1862 } |
| 1799 case Variable::PARAMETER: | 1863 case Variable::PARAMETER: |
| 1800 case Variable::LOCAL: | 1864 case Variable::LOCAL: |
| 1801 // Local var, const, or let variable. | 1865 // Local var, const, or let variable. |
| 1802 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { | 1866 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { |
| 1803 // Perform an initialization check for legacy const variables. | 1867 // Perform an initialization check for legacy const variables. |
| 1804 Node* current = environment()->Lookup(variable); | 1868 Node* current = environment()->Lookup(variable); |
| 1805 if (current->op() != the_hole->op()) { | 1869 if (current->op() != the_hole->op()) { |
| 1806 value = BuildHoleCheckSilent(current, value, current); | 1870 value = BuildHoleCheckSilent(current, value, current); |
| 1807 } | 1871 } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1951 DCHECK(environment()->GetControlDependency() == node); | 2015 DCHECK(environment()->GetControlDependency() == node); |
| 1952 | 2016 |
| 1953 StructuredGraphBuilder::Environment* continuation_env = environment(); | 2017 StructuredGraphBuilder::Environment* continuation_env = environment(); |
| 1954 // Create environment for the deoptimization block, and build the block. | 2018 // Create environment for the deoptimization block, and build the block. |
| 1955 StructuredGraphBuilder::Environment* deopt_env = | 2019 StructuredGraphBuilder::Environment* deopt_env = |
| 1956 CopyEnvironment(continuation_env); | 2020 CopyEnvironment(continuation_env); |
| 1957 set_environment(deopt_env); | 2021 set_environment(deopt_env); |
| 1958 | 2022 |
| 1959 NewNode(common()->LazyDeoptimization()); | 2023 NewNode(common()->LazyDeoptimization()); |
| 1960 | 2024 |
| 2025 // TODO(jarin) If ast_id.IsNone(), perhaps we should generate an empty |
| 2026 // deopt block and make sure there is no patch entry for this (so |
| 2027 // that the deoptimizer dies when trying to deoptimize here). |
| 2028 |
| 1961 Node* state_node = environment()->Checkpoint(ast_id); | 2029 Node* state_node = environment()->Checkpoint(ast_id); |
| 1962 | 2030 |
| 1963 Node* deoptimize_node = NewNode(common()->Deoptimize(), state_node); | 2031 Node* deoptimize_node = NewNode(common()->Deoptimize(), state_node); |
| 1964 | 2032 |
| 1965 UpdateControlDependencyToLeaveFunction(deoptimize_node); | 2033 UpdateControlDependencyToLeaveFunction(deoptimize_node); |
| 1966 | 2034 |
| 1967 // Continue with the original environment. | 2035 // Continue with the original environment. |
| 1968 set_environment(continuation_env); | 2036 set_environment(continuation_env); |
| 1969 | 2037 |
| 1970 NewNode(common()->Continuation()); | 2038 NewNode(common()->Continuation()); |
| 1971 } | 2039 } |
| 1972 } | 2040 } |
| 2041 |
| 2042 |
| 2043 void AstGraphBuilder::BuildLazyBailoutWithPushedNode(Node* node, |
| 2044 BailoutId ast_id) { |
| 2045 environment()->Push(node); |
| 2046 BuildLazyBailout(node, ast_id); |
| 2047 environment()->Pop(); |
| 2048 } |
| 1973 } | 2049 } |
| 1974 } | 2050 } |
| 1975 } // namespace v8::internal::compiler | 2051 } // namespace v8::internal::compiler |
| OLD | NEW |