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); |
| 767 // TODO(jarin): provide real bailout id. |
| 768 BuildLazyBailout(index_inc, BailoutId::None()); |
737 for_loop.Continue(); | 769 for_loop.Continue(); |
738 is_property_missing.Else(); | 770 is_property_missing.Else(); |
739 is_property_missing.End(); | 771 is_property_missing.End(); |
740 } | 772 } |
741 // Replace 'value' in environment. | 773 // Replace 'value' in environment. |
742 environment()->Push(res); | 774 environment()->Push(res); |
743 test_should_filter.Else(); | 775 test_should_filter.Else(); |
744 test_should_filter.End(); | 776 test_should_filter.End(); |
745 } | 777 } |
746 value = environment()->Pop(); | 778 value = environment()->Pop(); |
747 // Bind value and do loop body. | 779 // Bind value and do loop body. |
748 VisitForInAssignment(stmt->each(), value); | 780 VisitForInAssignment(stmt->each(), value); |
749 VisitIterationBody(stmt, &for_loop, 5); | 781 VisitIterationBody(stmt, &for_loop, 5); |
750 // Inc counter and continue. | 782 // Inc counter and continue. |
751 Node* index_inc = | 783 Node* index_inc = |
752 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | 784 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
753 environment()->Poke(0, index_inc); | 785 environment()->Poke(0, index_inc); |
| 786 // TODO(jarin): provide real bailout id. |
| 787 BuildLazyBailout(index_inc, BailoutId::None()); |
754 for_loop.EndBody(); | 788 for_loop.EndBody(); |
755 for_loop.EndLoop(); | 789 for_loop.EndLoop(); |
756 environment()->Drop(5); | 790 environment()->Drop(5); |
757 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 791 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
758 } | 792 } |
759 have_no_properties.End(); | 793 have_no_properties.End(); |
760 } | 794 } |
761 is_null.End(); | 795 is_null.End(); |
762 } | 796 } |
763 is_undefined.End(); | 797 is_undefined.End(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 compare_if.Then(); | 856 compare_if.Then(); |
823 Visit(expr->then_expression()); | 857 Visit(expr->then_expression()); |
824 compare_if.Else(); | 858 compare_if.Else(); |
825 Visit(expr->else_expression()); | 859 Visit(expr->else_expression()); |
826 compare_if.End(); | 860 compare_if.End(); |
827 ast_context()->ReplaceValue(); | 861 ast_context()->ReplaceValue(); |
828 } | 862 } |
829 | 863 |
830 | 864 |
831 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 865 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
832 Node* value = BuildVariableLoad(expr->var()); | 866 Node* value = BuildVariableLoad(expr->var(), expr->id()); |
833 ast_context()->ProduceValue(value); | 867 ast_context()->ProduceValue(value); |
834 } | 868 } |
835 | 869 |
836 | 870 |
837 void AstGraphBuilder::VisitLiteral(Literal* expr) { | 871 void AstGraphBuilder::VisitLiteral(Literal* expr) { |
838 Node* value = jsgraph()->Constant(expr->value()); | 872 Node* value = jsgraph()->Constant(expr->value()); |
839 ast_context()->ProduceValue(value); | 873 ast_context()->ProduceValue(value); |
840 } | 874 } |
841 | 875 |
842 | 876 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 923 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
890 // Fall through. | 924 // Fall through. |
891 case ObjectLiteral::Property::COMPUTED: { | 925 case ObjectLiteral::Property::COMPUTED: { |
892 // It is safe to use [[Put]] here because the boilerplate already | 926 // It is safe to use [[Put]] here because the boilerplate already |
893 // contains computed properties with an uninitialized value. | 927 // contains computed properties with an uninitialized value. |
894 if (key->value()->IsInternalizedString()) { | 928 if (key->value()->IsInternalizedString()) { |
895 if (property->emit_store()) { | 929 if (property->emit_store()) { |
896 VisitForValue(property->value()); | 930 VisitForValue(property->value()); |
897 Node* value = environment()->Pop(); | 931 Node* value = environment()->Pop(); |
898 PrintableUnique<Name> name = MakeUnique(key->AsPropertyName()); | 932 PrintableUnique<Name> name = MakeUnique(key->AsPropertyName()); |
899 NewNode(javascript()->StoreNamed(name), literal, value); | 933 Node* store = |
| 934 NewNode(javascript()->StoreNamed(name), literal, value); |
| 935 BuildLazyBailout(store, key->id()); |
900 } else { | 936 } else { |
901 VisitForEffect(property->value()); | 937 VisitForEffect(property->value()); |
902 } | 938 } |
903 break; | 939 break; |
904 } | 940 } |
905 environment()->Push(literal); // Duplicate receiver. | 941 environment()->Push(literal); // Duplicate receiver. |
906 VisitForValue(property->key()); | 942 VisitForValue(property->key()); |
907 VisitForValue(property->value()); | 943 VisitForValue(property->value()); |
908 Node* value = environment()->Pop(); | 944 Node* value = environment()->Pop(); |
909 Node* key = environment()->Pop(); | 945 Node* key = environment()->Pop(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 | 1016 |
981 // Create nodes to evaluate all the non-constant subexpressions and to store | 1017 // Create nodes to evaluate all the non-constant subexpressions and to store |
982 // them into the newly cloned array. | 1018 // them into the newly cloned array. |
983 for (int i = 0; i < expr->values()->length(); i++) { | 1019 for (int i = 0; i < expr->values()->length(); i++) { |
984 Expression* subexpr = expr->values()->at(i); | 1020 Expression* subexpr = expr->values()->at(i); |
985 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 1021 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
986 | 1022 |
987 VisitForValue(subexpr); | 1023 VisitForValue(subexpr); |
988 Node* value = environment()->Pop(); | 1024 Node* value = environment()->Pop(); |
989 Node* index = jsgraph()->Constant(i); | 1025 Node* index = jsgraph()->Constant(i); |
990 NewNode(javascript()->StoreProperty(), literal, index, value); | 1026 Node* store = NewNode(javascript()->StoreProperty(), literal, index, value); |
| 1027 BuildLazyBailout(store, expr->GetIdForElement(i)); |
991 } | 1028 } |
992 | 1029 |
993 environment()->Pop(); // Array literal index. | 1030 environment()->Pop(); // Array literal index. |
994 ast_context()->ProduceValue(environment()->Pop()); | 1031 ast_context()->ProduceValue(environment()->Pop()); |
995 } | 1032 } |
996 | 1033 |
997 | 1034 |
998 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) { | 1035 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value) { |
999 DCHECK(expr->IsValidReferenceExpression()); | 1036 DCHECK(expr->IsValidReferenceExpression()); |
1000 | 1037 |
1001 // Left-hand side can only be a property, a global or a variable slot. | 1038 // Left-hand side can only be a property, a global or a variable slot. |
1002 Property* property = expr->AsProperty(); | 1039 Property* property = expr->AsProperty(); |
1003 LhsKind assign_type = DetermineLhsKind(expr); | 1040 LhsKind assign_type = DetermineLhsKind(expr); |
1004 | 1041 |
1005 // Evaluate LHS expression and store the value. | 1042 // Evaluate LHS expression and store the value. |
1006 switch (assign_type) { | 1043 switch (assign_type) { |
1007 case VARIABLE: { | 1044 case VARIABLE: { |
1008 Variable* var = expr->AsVariableProxy()->var(); | 1045 Variable* var = expr->AsVariableProxy()->var(); |
1009 BuildVariableAssignment(var, value, Token::ASSIGN); | 1046 // TODO(jarin) Fill in the correct bailout id. |
| 1047 BuildVariableAssignment(var, value, Token::ASSIGN, BailoutId::None()); |
1010 break; | 1048 break; |
1011 } | 1049 } |
1012 case NAMED_PROPERTY: { | 1050 case NAMED_PROPERTY: { |
1013 environment()->Push(value); | 1051 environment()->Push(value); |
1014 VisitForValue(property->obj()); | 1052 VisitForValue(property->obj()); |
1015 Node* object = environment()->Pop(); | 1053 Node* object = environment()->Pop(); |
1016 value = environment()->Pop(); | 1054 value = environment()->Pop(); |
1017 PrintableUnique<Name> name = | 1055 PrintableUnique<Name> name = |
1018 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1056 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1019 NewNode(javascript()->StoreNamed(name), object, value); | 1057 Node* store = NewNode(javascript()->StoreNamed(name), object, value); |
| 1058 // TODO(jarin) Fill in the correct bailout id. |
| 1059 BuildLazyBailout(store, BailoutId::None()); |
1020 break; | 1060 break; |
1021 } | 1061 } |
1022 case KEYED_PROPERTY: { | 1062 case KEYED_PROPERTY: { |
1023 environment()->Push(value); | 1063 environment()->Push(value); |
1024 VisitForValue(property->obj()); | 1064 VisitForValue(property->obj()); |
1025 VisitForValue(property->key()); | 1065 VisitForValue(property->key()); |
1026 Node* key = environment()->Pop(); | 1066 Node* key = environment()->Pop(); |
1027 Node* object = environment()->Pop(); | 1067 Node* object = environment()->Pop(); |
1028 value = environment()->Pop(); | 1068 value = environment()->Pop(); |
1029 NewNode(javascript()->StoreProperty(), object, key, value); | 1069 Node* store = NewNode(javascript()->StoreProperty(), object, key, value); |
| 1070 // TODO(jarin) Fill in the correct bailout id. |
| 1071 BuildLazyBailout(store, BailoutId::None()); |
1030 break; | 1072 break; |
1031 } | 1073 } |
1032 } | 1074 } |
1033 } | 1075 } |
1034 | 1076 |
1035 | 1077 |
1036 void AstGraphBuilder::VisitAssignment(Assignment* expr) { | 1078 void AstGraphBuilder::VisitAssignment(Assignment* expr) { |
1037 DCHECK(expr->target()->IsValidReferenceExpression()); | 1079 DCHECK(expr->target()->IsValidReferenceExpression()); |
1038 | 1080 |
1039 // Left-hand side can only be a property, a global or a variable slot. | 1081 // Left-hand side can only be a property, a global or a variable slot. |
(...skipping 15 matching lines...) Expand all Loading... |
1055 } | 1097 } |
1056 } | 1098 } |
1057 | 1099 |
1058 // Evaluate the value and potentially handle compound assignments by loading | 1100 // Evaluate the value and potentially handle compound assignments by loading |
1059 // the left-hand side value and performing a binary operation. | 1101 // the left-hand side value and performing a binary operation. |
1060 if (expr->is_compound()) { | 1102 if (expr->is_compound()) { |
1061 Node* old_value = NULL; | 1103 Node* old_value = NULL; |
1062 switch (assign_type) { | 1104 switch (assign_type) { |
1063 case VARIABLE: { | 1105 case VARIABLE: { |
1064 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1106 Variable* variable = expr->target()->AsVariableProxy()->var(); |
1065 old_value = BuildVariableLoad(variable); | 1107 old_value = BuildVariableLoad(variable, expr->target()->id()); |
1066 break; | 1108 break; |
1067 } | 1109 } |
1068 case NAMED_PROPERTY: { | 1110 case NAMED_PROPERTY: { |
1069 Node* object = environment()->Top(); | 1111 Node* object = environment()->Top(); |
1070 PrintableUnique<Name> name = | 1112 PrintableUnique<Name> name = |
1071 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1113 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1072 old_value = NewNode(javascript()->LoadNamed(name), object); | 1114 old_value = NewNode(javascript()->LoadNamed(name), object); |
| 1115 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
1073 break; | 1116 break; |
1074 } | 1117 } |
1075 case KEYED_PROPERTY: { | 1118 case KEYED_PROPERTY: { |
1076 Node* key = environment()->Top(); | 1119 Node* key = environment()->Top(); |
1077 Node* object = environment()->Peek(1); | 1120 Node* object = environment()->Peek(1); |
1078 old_value = NewNode(javascript()->LoadProperty(), object, key); | 1121 old_value = NewNode(javascript()->LoadProperty(), object, key); |
| 1122 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
1079 break; | 1123 break; |
1080 } | 1124 } |
1081 } | 1125 } |
1082 environment()->Push(old_value); | 1126 environment()->Push(old_value); |
1083 VisitForValue(expr->value()); | 1127 VisitForValue(expr->value()); |
1084 Node* right = environment()->Pop(); | 1128 Node* right = environment()->Pop(); |
1085 Node* left = environment()->Pop(); | 1129 Node* left = environment()->Pop(); |
1086 Node* value = BuildBinaryOp(left, right, expr->binary_op()); | 1130 Node* value = BuildBinaryOp(left, right, expr->binary_op()); |
1087 environment()->Push(value); | 1131 environment()->Push(value); |
| 1132 BuildLazyBailout(value, expr->binary_operation()->id()); |
1088 } else { | 1133 } else { |
1089 VisitForValue(expr->value()); | 1134 VisitForValue(expr->value()); |
1090 } | 1135 } |
1091 | 1136 |
1092 // Store the value. | 1137 // Store the value. |
1093 Node* value = environment()->Pop(); | 1138 Node* value = environment()->Pop(); |
1094 switch (assign_type) { | 1139 switch (assign_type) { |
1095 case VARIABLE: { | 1140 case VARIABLE: { |
1096 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1141 Variable* variable = expr->target()->AsVariableProxy()->var(); |
1097 BuildVariableAssignment(variable, value, expr->op()); | 1142 BuildVariableAssignment(variable, value, expr->op(), |
| 1143 expr->AssignmentId()); |
1098 break; | 1144 break; |
1099 } | 1145 } |
1100 case NAMED_PROPERTY: { | 1146 case NAMED_PROPERTY: { |
1101 Node* object = environment()->Pop(); | 1147 Node* object = environment()->Pop(); |
1102 PrintableUnique<Name> name = | 1148 PrintableUnique<Name> name = |
1103 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1149 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1104 NewNode(javascript()->StoreNamed(name), object, value); | 1150 Node* store = NewNode(javascript()->StoreNamed(name), object, value); |
| 1151 BuildLazyBailout(store, expr->AssignmentId()); |
1105 break; | 1152 break; |
1106 } | 1153 } |
1107 case KEYED_PROPERTY: { | 1154 case KEYED_PROPERTY: { |
1108 Node* key = environment()->Pop(); | 1155 Node* key = environment()->Pop(); |
1109 Node* object = environment()->Pop(); | 1156 Node* object = environment()->Pop(); |
1110 NewNode(javascript()->StoreProperty(), object, key, value); | 1157 Node* store = NewNode(javascript()->StoreProperty(), object, key, value); |
| 1158 BuildLazyBailout(store, expr->AssignmentId()); |
1111 break; | 1159 break; |
1112 } | 1160 } |
1113 } | 1161 } |
1114 | 1162 |
1115 ast_context()->ProduceValue(value); | 1163 ast_context()->ProduceValue(value); |
1116 } | 1164 } |
1117 | 1165 |
1118 | 1166 |
1119 void AstGraphBuilder::VisitYield(Yield* expr) { | 1167 void AstGraphBuilder::VisitYield(Yield* expr) { |
1120 VisitForValue(expr->generator_object()); | 1168 VisitForValue(expr->generator_object()); |
(...skipping 22 matching lines...) Expand all Loading... |
1143 PrintableUnique<Name> name = | 1191 PrintableUnique<Name> name = |
1144 MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); | 1192 MakeUnique(expr->key()->AsLiteral()->AsPropertyName()); |
1145 value = NewNode(javascript()->LoadNamed(name), object); | 1193 value = NewNode(javascript()->LoadNamed(name), object); |
1146 } else { | 1194 } else { |
1147 VisitForValue(expr->obj()); | 1195 VisitForValue(expr->obj()); |
1148 VisitForValue(expr->key()); | 1196 VisitForValue(expr->key()); |
1149 Node* key = environment()->Pop(); | 1197 Node* key = environment()->Pop(); |
1150 Node* object = environment()->Pop(); | 1198 Node* object = environment()->Pop(); |
1151 value = NewNode(javascript()->LoadProperty(), object, key); | 1199 value = NewNode(javascript()->LoadProperty(), object, key); |
1152 } | 1200 } |
1153 ast_context()->ProduceValue(value); | 1201 ast_context()->ProduceValueWithLazyBailout(value); |
1154 } | 1202 } |
1155 | 1203 |
1156 | 1204 |
1157 void AstGraphBuilder::VisitCall(Call* expr) { | 1205 void AstGraphBuilder::VisitCall(Call* expr) { |
1158 Expression* callee = expr->expression(); | 1206 Expression* callee = expr->expression(); |
1159 Call::CallType call_type = expr->GetCallType(isolate()); | 1207 Call::CallType call_type = expr->GetCallType(isolate()); |
1160 | 1208 |
1161 // Prepare the callee and the receiver to the function call. This depends on | 1209 // Prepare the callee and the receiver to the function call. This depends on |
1162 // the semantics of the underlying call type. | 1210 // the semantics of the underlying call type. |
1163 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; | 1211 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
1164 Node* receiver_value = NULL; | 1212 Node* receiver_value = NULL; |
1165 Node* callee_value = NULL; | 1213 Node* callee_value = NULL; |
1166 bool possibly_eval = false; | 1214 bool possibly_eval = false; |
1167 switch (call_type) { | 1215 switch (call_type) { |
1168 case Call::GLOBAL_CALL: { | 1216 case Call::GLOBAL_CALL: { |
1169 Variable* variable = callee->AsVariableProxy()->var(); | 1217 Variable* variable = callee->AsVariableProxy()->var(); |
1170 callee_value = BuildVariableLoad(variable); | 1218 callee_value = BuildVariableLoad(variable, expr->expression()->id()); |
1171 receiver_value = jsgraph()->UndefinedConstant(); | 1219 receiver_value = jsgraph()->UndefinedConstant(); |
1172 break; | 1220 break; |
1173 } | 1221 } |
1174 case Call::LOOKUP_SLOT_CALL: { | 1222 case Call::LOOKUP_SLOT_CALL: { |
1175 Variable* variable = callee->AsVariableProxy()->var(); | 1223 Variable* variable = callee->AsVariableProxy()->var(); |
1176 DCHECK(variable->location() == Variable::LOOKUP); | 1224 DCHECK(variable->location() == Variable::LOOKUP); |
1177 Node* name = jsgraph()->Constant(variable->name()); | 1225 Node* name = jsgraph()->Constant(variable->name()); |
1178 Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); | 1226 Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); |
1179 Node* pair = NewNode(op, current_context(), name); | 1227 Node* pair = NewNode(op, current_context(), name); |
1180 callee_value = NewNode(common()->Projection(0), pair); | 1228 callee_value = NewNode(common()->Projection(0), pair); |
1181 receiver_value = NewNode(common()->Projection(1), pair); | 1229 receiver_value = NewNode(common()->Projection(1), pair); |
1182 break; | 1230 break; |
1183 } | 1231 } |
1184 case Call::PROPERTY_CALL: { | 1232 case Call::PROPERTY_CALL: { |
1185 Property* property = callee->AsProperty(); | 1233 Property* property = callee->AsProperty(); |
1186 VisitForValue(property->obj()); | 1234 VisitForValue(property->obj()); |
1187 Node* object = environment()->Top(); | 1235 Node* object = environment()->Top(); |
1188 if (property->key()->IsPropertyName()) { | 1236 if (property->key()->IsPropertyName()) { |
1189 PrintableUnique<Name> name = | 1237 PrintableUnique<Name> name = |
1190 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1238 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1191 callee_value = NewNode(javascript()->LoadNamed(name), object); | 1239 callee_value = NewNode(javascript()->LoadNamed(name), object); |
1192 } else { | 1240 } else { |
1193 VisitForValue(property->key()); | 1241 VisitForValue(property->key()); |
1194 Node* key = environment()->Pop(); | 1242 Node* key = environment()->Pop(); |
1195 callee_value = NewNode(javascript()->LoadProperty(), object, key); | 1243 callee_value = NewNode(javascript()->LoadProperty(), object, key); |
1196 } | 1244 } |
| 1245 BuildLazyBailoutWithPushedNode(callee_value, property->LoadId()); |
1197 receiver_value = environment()->Pop(); | 1246 receiver_value = environment()->Pop(); |
1198 // Note that a PROPERTY_CALL requires the receiver to be wrapped into an | 1247 // 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, | 1248 // object for sloppy callees. This could also be modeled explicitly here, |
1200 // thereby obsoleting the need for a flag to the call operator. | 1249 // thereby obsoleting the need for a flag to the call operator. |
1201 flags = CALL_AS_METHOD; | 1250 flags = CALL_AS_METHOD; |
1202 break; | 1251 break; |
1203 } | 1252 } |
1204 case Call::POSSIBLY_EVAL_CALL: | 1253 case Call::POSSIBLY_EVAL_CALL: |
1205 possibly_eval = true; | 1254 possibly_eval = true; |
1206 // Fall through. | 1255 // Fall through. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 Node* new_receiver = NewNode(common()->Projection(1), pair); | 1290 Node* new_receiver = NewNode(common()->Projection(1), pair); |
1242 | 1291 |
1243 // Patch callee and receiver on the environment. | 1292 // Patch callee and receiver on the environment. |
1244 environment()->Poke(arg_count + 1, new_callee); | 1293 environment()->Poke(arg_count + 1, new_callee); |
1245 environment()->Poke(arg_count + 0, new_receiver); | 1294 environment()->Poke(arg_count + 0, new_receiver); |
1246 } | 1295 } |
1247 | 1296 |
1248 // Create node to perform the function call. | 1297 // Create node to perform the function call. |
1249 Operator* call = javascript()->Call(args->length() + 2, flags); | 1298 Operator* call = javascript()->Call(args->length() + 2, flags); |
1250 Node* value = ProcessArguments(call, args->length() + 2); | 1299 Node* value = ProcessArguments(call, args->length() + 2); |
1251 ast_context()->ProduceValue(value); | 1300 ast_context()->ProduceValueWithLazyBailout(value); |
1252 } | 1301 } |
1253 | 1302 |
1254 | 1303 |
1255 void AstGraphBuilder::VisitCallNew(CallNew* expr) { | 1304 void AstGraphBuilder::VisitCallNew(CallNew* expr) { |
1256 VisitForValue(expr->expression()); | 1305 VisitForValue(expr->expression()); |
1257 | 1306 |
1258 // Evaluate all arguments to the construct call. | 1307 // Evaluate all arguments to the construct call. |
1259 ZoneList<Expression*>* args = expr->arguments(); | 1308 ZoneList<Expression*>* args = expr->arguments(); |
1260 VisitForValues(args); | 1309 VisitForValues(args); |
1261 | 1310 |
1262 // Create node to perform the construct call. | 1311 // Create node to perform the construct call. |
1263 Operator* call = javascript()->CallNew(args->length() + 1); | 1312 Operator* call = javascript()->CallNew(args->length() + 1); |
1264 Node* value = ProcessArguments(call, args->length() + 1); | 1313 Node* value = ProcessArguments(call, args->length() + 1); |
1265 ast_context()->ProduceValue(value); | 1314 ast_context()->ProduceValueWithLazyBailout(value); |
1266 } | 1315 } |
1267 | 1316 |
1268 | 1317 |
1269 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { | 1318 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { |
1270 Handle<String> name = expr->name(); | 1319 Handle<String> name = expr->name(); |
1271 | 1320 |
1272 // The callee and the receiver both have to be pushed onto the operand stack | 1321 // The callee and the receiver both have to be pushed onto the operand stack |
1273 // before arguments are being evaluated. | 1322 // before arguments are being evaluated. |
1274 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; | 1323 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
1275 Node* receiver_value = BuildLoadBuiltinsObject(); | 1324 Node* receiver_value = BuildLoadBuiltinsObject(); |
1276 PrintableUnique<String> unique = MakeUnique(name); | 1325 PrintableUnique<String> unique = MakeUnique(name); |
1277 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); | 1326 Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value); |
1278 environment()->Push(callee_value); | 1327 environment()->Push(callee_value); |
| 1328 // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft |
| 1329 // refuses to optimize functions with jsruntime calls). |
| 1330 BuildLazyBailout(callee_value, BailoutId::None()); |
1279 environment()->Push(receiver_value); | 1331 environment()->Push(receiver_value); |
1280 | 1332 |
1281 // Evaluate all arguments to the JS runtime call. | 1333 // Evaluate all arguments to the JS runtime call. |
1282 ZoneList<Expression*>* args = expr->arguments(); | 1334 ZoneList<Expression*>* args = expr->arguments(); |
1283 VisitForValues(args); | 1335 VisitForValues(args); |
1284 | 1336 |
1285 // Create node to perform the JS runtime call. | 1337 // Create node to perform the JS runtime call. |
1286 Operator* call = javascript()->Call(args->length() + 2, flags); | 1338 Operator* call = javascript()->Call(args->length() + 2, flags); |
1287 Node* value = ProcessArguments(call, args->length() + 2); | 1339 Node* value = ProcessArguments(call, args->length() + 2); |
1288 ast_context()->ProduceValue(value); | 1340 ast_context()->ProduceValueWithLazyBailout(value); |
1289 } | 1341 } |
1290 | 1342 |
1291 | 1343 |
1292 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 1344 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
1293 const Runtime::Function* function = expr->function(); | 1345 const Runtime::Function* function = expr->function(); |
1294 | 1346 |
1295 // Handle calls to runtime functions implemented in JavaScript separately as | 1347 // Handle calls to runtime functions implemented in JavaScript separately as |
1296 // the call follows JavaScript ABI and the callee is statically unknown. | 1348 // the call follows JavaScript ABI and the callee is statically unknown. |
1297 if (expr->is_jsruntime()) { | 1349 if (expr->is_jsruntime()) { |
1298 DCHECK(function == NULL && expr->name()->length() > 0); | 1350 DCHECK(function == NULL && expr->name()->length() > 0); |
1299 return VisitCallJSRuntime(expr); | 1351 return VisitCallJSRuntime(expr); |
1300 } | 1352 } |
1301 | 1353 |
1302 // Evaluate all arguments to the runtime call. | 1354 // Evaluate all arguments to the runtime call. |
1303 ZoneList<Expression*>* args = expr->arguments(); | 1355 ZoneList<Expression*>* args = expr->arguments(); |
1304 VisitForValues(args); | 1356 VisitForValues(args); |
1305 | 1357 |
1306 // Create node to perform the runtime call. | 1358 // Create node to perform the runtime call. |
1307 Runtime::FunctionId functionId = function->function_id; | 1359 Runtime::FunctionId functionId = function->function_id; |
1308 Operator* call = javascript()->Runtime(functionId, args->length()); | 1360 Operator* call = javascript()->Runtime(functionId, args->length()); |
1309 Node* value = ProcessArguments(call, args->length()); | 1361 Node* value = ProcessArguments(call, args->length()); |
1310 ast_context()->ProduceValue(value); | 1362 ast_context()->ProduceValueWithLazyBailout(value); |
1311 | |
1312 BuildLazyBailout(value, expr->id()); | |
1313 } | 1363 } |
1314 | 1364 |
1315 | 1365 |
1316 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 1366 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
1317 switch (expr->op()) { | 1367 switch (expr->op()) { |
1318 case Token::DELETE: | 1368 case Token::DELETE: |
1319 return VisitDelete(expr); | 1369 return VisitDelete(expr); |
1320 case Token::VOID: | 1370 case Token::VOID: |
1321 return VisitVoid(expr); | 1371 return VisitVoid(expr); |
1322 case Token::TYPEOF: | 1372 case Token::TYPEOF: |
(...skipping 16 matching lines...) Expand all Loading... |
1339 // Reserve space for result of postfix operation. | 1389 // Reserve space for result of postfix operation. |
1340 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect(); | 1390 bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect(); |
1341 if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant()); | 1391 if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant()); |
1342 | 1392 |
1343 // Evaluate LHS expression and get old value. | 1393 // Evaluate LHS expression and get old value. |
1344 Node* old_value = NULL; | 1394 Node* old_value = NULL; |
1345 int stack_depth = -1; | 1395 int stack_depth = -1; |
1346 switch (assign_type) { | 1396 switch (assign_type) { |
1347 case VARIABLE: { | 1397 case VARIABLE: { |
1348 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 1398 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
1349 old_value = BuildVariableLoad(variable); | 1399 old_value = BuildVariableLoad(variable, expr->expression()->id()); |
1350 stack_depth = 0; | 1400 stack_depth = 0; |
1351 break; | 1401 break; |
1352 } | 1402 } |
1353 case NAMED_PROPERTY: { | 1403 case NAMED_PROPERTY: { |
1354 VisitForValue(property->obj()); | 1404 VisitForValue(property->obj()); |
1355 Node* object = environment()->Top(); | 1405 Node* object = environment()->Top(); |
1356 PrintableUnique<Name> name = | 1406 PrintableUnique<Name> name = |
1357 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1407 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1358 old_value = NewNode(javascript()->LoadNamed(name), object); | 1408 old_value = NewNode(javascript()->LoadNamed(name), object); |
| 1409 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
1359 stack_depth = 1; | 1410 stack_depth = 1; |
1360 break; | 1411 break; |
1361 } | 1412 } |
1362 case KEYED_PROPERTY: { | 1413 case KEYED_PROPERTY: { |
1363 VisitForValue(property->obj()); | 1414 VisitForValue(property->obj()); |
1364 VisitForValue(property->key()); | 1415 VisitForValue(property->key()); |
1365 Node* key = environment()->Top(); | 1416 Node* key = environment()->Top(); |
1366 Node* object = environment()->Peek(1); | 1417 Node* object = environment()->Peek(1); |
1367 old_value = NewNode(javascript()->LoadProperty(), object, key); | 1418 old_value = NewNode(javascript()->LoadProperty(), object, key); |
| 1419 BuildLazyBailoutWithPushedNode(old_value, property->LoadId()); |
1368 stack_depth = 2; | 1420 stack_depth = 2; |
1369 break; | 1421 break; |
1370 } | 1422 } |
1371 } | 1423 } |
1372 | 1424 |
1373 // Convert old value into a number. | 1425 // Convert old value into a number. |
1374 old_value = NewNode(javascript()->ToNumber(), old_value); | 1426 old_value = NewNode(javascript()->ToNumber(), old_value); |
1375 | 1427 |
1376 // Save result for postfix expressions at correct stack depth. | 1428 // Save result for postfix expressions at correct stack depth. |
1377 if (is_postfix) environment()->Poke(stack_depth, old_value); | 1429 if (is_postfix) environment()->Poke(stack_depth, old_value); |
1378 | 1430 |
1379 // Create node to perform +1/-1 operation. | 1431 // Create node to perform +1/-1 operation. |
1380 Node* value = | 1432 Node* value = |
1381 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); | 1433 BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op()); |
| 1434 // TODO(jarin) Insert proper bailout id here (will need to change |
| 1435 // full code generator). |
| 1436 BuildLazyBailout(value, BailoutId::None()); |
1382 | 1437 |
1383 // Store the value. | 1438 // Store the value. |
1384 switch (assign_type) { | 1439 switch (assign_type) { |
1385 case VARIABLE: { | 1440 case VARIABLE: { |
1386 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 1441 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
1387 BuildVariableAssignment(variable, value, expr->op()); | 1442 BuildVariableAssignment(variable, value, expr->op(), |
| 1443 expr->AssignmentId()); |
1388 break; | 1444 break; |
1389 } | 1445 } |
1390 case NAMED_PROPERTY: { | 1446 case NAMED_PROPERTY: { |
1391 Node* object = environment()->Pop(); | 1447 Node* object = environment()->Pop(); |
1392 PrintableUnique<Name> name = | 1448 PrintableUnique<Name> name = |
1393 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); | 1449 MakeUnique(property->key()->AsLiteral()->AsPropertyName()); |
1394 NewNode(javascript()->StoreNamed(name), object, value); | 1450 Node* store = NewNode(javascript()->StoreNamed(name), object, value); |
| 1451 BuildLazyBailout(store, expr->AssignmentId()); |
1395 break; | 1452 break; |
1396 } | 1453 } |
1397 case KEYED_PROPERTY: { | 1454 case KEYED_PROPERTY: { |
1398 Node* key = environment()->Pop(); | 1455 Node* key = environment()->Pop(); |
1399 Node* object = environment()->Pop(); | 1456 Node* object = environment()->Pop(); |
1400 NewNode(javascript()->StoreProperty(), object, key, value); | 1457 Node* store = NewNode(javascript()->StoreProperty(), object, key, value); |
| 1458 BuildLazyBailout(store, expr->AssignmentId()); |
1401 break; | 1459 break; |
1402 } | 1460 } |
1403 } | 1461 } |
1404 | 1462 |
1405 // Restore old value for postfix expressions. | 1463 // Restore old value for postfix expressions. |
1406 if (is_postfix) value = environment()->Pop(); | 1464 if (is_postfix) value = environment()->Pop(); |
1407 | 1465 |
1408 ast_context()->ProduceValue(value); | 1466 ast_context()->ProduceValue(value); |
1409 } | 1467 } |
1410 | 1468 |
1411 | 1469 |
1412 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 1470 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
1413 switch (expr->op()) { | 1471 switch (expr->op()) { |
1414 case Token::COMMA: | 1472 case Token::COMMA: |
1415 return VisitComma(expr); | 1473 return VisitComma(expr); |
1416 case Token::OR: | 1474 case Token::OR: |
1417 case Token::AND: | 1475 case Token::AND: |
1418 return VisitLogicalExpression(expr); | 1476 return VisitLogicalExpression(expr); |
1419 default: { | 1477 default: { |
1420 VisitForValue(expr->left()); | 1478 VisitForValue(expr->left()); |
1421 VisitForValue(expr->right()); | 1479 VisitForValue(expr->right()); |
1422 Node* right = environment()->Pop(); | 1480 Node* right = environment()->Pop(); |
1423 Node* left = environment()->Pop(); | 1481 Node* left = environment()->Pop(); |
1424 Node* value = BuildBinaryOp(left, right, expr->op()); | 1482 Node* value = BuildBinaryOp(left, right, expr->op()); |
1425 ast_context()->ProduceValue(value); | 1483 ast_context()->ProduceValueWithLazyBailout(value); |
1426 } | 1484 } |
1427 } | 1485 } |
1428 } | 1486 } |
1429 | 1487 |
1430 | 1488 |
1431 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 1489 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
1432 Operator* op; | 1490 Operator* op; |
1433 switch (expr->op()) { | 1491 switch (expr->op()) { |
1434 case Token::EQ: | 1492 case Token::EQ: |
1435 op = javascript()->Equal(); | 1493 op = javascript()->Equal(); |
(...skipping 28 matching lines...) Expand all Loading... |
1464 default: | 1522 default: |
1465 op = NULL; | 1523 op = NULL; |
1466 UNREACHABLE(); | 1524 UNREACHABLE(); |
1467 } | 1525 } |
1468 VisitForValue(expr->left()); | 1526 VisitForValue(expr->left()); |
1469 VisitForValue(expr->right()); | 1527 VisitForValue(expr->right()); |
1470 Node* right = environment()->Pop(); | 1528 Node* right = environment()->Pop(); |
1471 Node* left = environment()->Pop(); | 1529 Node* left = environment()->Pop(); |
1472 Node* value = NewNode(op, left, right); | 1530 Node* value = NewNode(op, left, right); |
1473 ast_context()->ProduceValue(value); | 1531 ast_context()->ProduceValue(value); |
| 1532 |
| 1533 BuildLazyBailout(value, expr->id()); |
1474 } | 1534 } |
1475 | 1535 |
1476 | 1536 |
1477 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 1537 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
1478 Node* value = GetFunctionClosure(); | 1538 Node* value = GetFunctionClosure(); |
1479 ast_context()->ProduceValue(value); | 1539 ast_context()->ProduceValue(value); |
1480 } | 1540 } |
1481 | 1541 |
1482 | 1542 |
1483 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); } | 1543 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 ast_context()->ProduceValue(value); | 1603 ast_context()->ProduceValue(value); |
1544 } | 1604 } |
1545 | 1605 |
1546 | 1606 |
1547 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 1607 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
1548 Node* operand; | 1608 Node* operand; |
1549 if (expr->expression()->IsVariableProxy()) { | 1609 if (expr->expression()->IsVariableProxy()) { |
1550 // Typeof does not throw a reference error on global variables, hence we | 1610 // 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. | 1611 // perform a non-contextual load in case the operand is a variable proxy. |
1552 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 1612 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
1553 operand = BuildVariableLoad(variable, NOT_CONTEXTUAL); | 1613 operand = |
| 1614 BuildVariableLoad(variable, expr->expression()->id(), NOT_CONTEXTUAL); |
1554 } else { | 1615 } else { |
1555 VisitForValue(expr->expression()); | 1616 VisitForValue(expr->expression()); |
1556 operand = environment()->Pop(); | 1617 operand = environment()->Pop(); |
1557 } | 1618 } |
1558 Node* value = NewNode(javascript()->TypeOf(), operand); | 1619 Node* value = NewNode(javascript()->TypeOf(), operand); |
1559 ast_context()->ProduceValue(value); | 1620 ast_context()->ProduceValue(value); |
1560 } | 1621 } |
1561 | 1622 |
1562 | 1623 |
1563 void AstGraphBuilder::VisitNot(UnaryOperation* expr) { | 1624 void AstGraphBuilder::VisitNot(UnaryOperation* expr) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1643 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { | 1704 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { |
1644 if (arguments == NULL) return NULL; | 1705 if (arguments == NULL) return NULL; |
1645 | 1706 |
1646 // Allocate and initialize a new arguments object. | 1707 // Allocate and initialize a new arguments object. |
1647 Node* callee = GetFunctionClosure(); | 1708 Node* callee = GetFunctionClosure(); |
1648 Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); | 1709 Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); |
1649 Node* object = NewNode(op, callee); | 1710 Node* object = NewNode(op, callee); |
1650 | 1711 |
1651 // Assign the object to the arguments variable. | 1712 // Assign the object to the arguments variable. |
1652 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); | 1713 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
1653 BuildVariableAssignment(arguments, object, Token::ASSIGN); | 1714 // This should never lazy deopt, so it is fine to send invalid bailout id. |
| 1715 BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None()); |
1654 | 1716 |
1655 return object; | 1717 return object; |
1656 } | 1718 } |
1657 | 1719 |
1658 | 1720 |
1659 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, | 1721 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, |
1660 Node* not_hole) { | 1722 Node* not_hole) { |
1661 IfBuilder hole_check(this); | 1723 IfBuilder hole_check(this); |
1662 Node* the_hole = jsgraph()->TheHoleConstant(); | 1724 Node* the_hole = jsgraph()->TheHoleConstant(); |
1663 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); | 1725 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); |
(...skipping 16 matching lines...) Expand all Loading... |
1680 hole_check.Then(); | 1742 hole_check.Then(); |
1681 environment()->Push(BuildThrowReferenceError(variable)); | 1743 environment()->Push(BuildThrowReferenceError(variable)); |
1682 hole_check.Else(); | 1744 hole_check.Else(); |
1683 environment()->Push(not_hole); | 1745 environment()->Push(not_hole); |
1684 hole_check.End(); | 1746 hole_check.End(); |
1685 return environment()->Pop(); | 1747 return environment()->Pop(); |
1686 } | 1748 } |
1687 | 1749 |
1688 | 1750 |
1689 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, | 1751 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
| 1752 BailoutId bailout_id, |
1690 ContextualMode contextual_mode) { | 1753 ContextualMode contextual_mode) { |
1691 Node* the_hole = jsgraph()->TheHoleConstant(); | 1754 Node* the_hole = jsgraph()->TheHoleConstant(); |
1692 VariableMode mode = variable->mode(); | 1755 VariableMode mode = variable->mode(); |
1693 switch (variable->location()) { | 1756 switch (variable->location()) { |
1694 case Variable::UNALLOCATED: { | 1757 case Variable::UNALLOCATED: { |
1695 // Global var, const, or let variable. | 1758 // Global var, const, or let variable. |
1696 Node* global = BuildLoadGlobalObject(); | 1759 Node* global = BuildLoadGlobalObject(); |
1697 PrintableUnique<Name> name = MakeUnique(variable->name()); | 1760 PrintableUnique<Name> name = MakeUnique(variable->name()); |
1698 Operator* op = javascript()->LoadNamed(name, contextual_mode); | 1761 Operator* op = javascript()->LoadNamed(name, contextual_mode); |
1699 return NewNode(op, global); | 1762 Node* node = NewNode(op, global); |
| 1763 BuildLazyBailoutWithPushedNode(node, bailout_id); |
| 1764 return node; |
1700 } | 1765 } |
1701 case Variable::PARAMETER: | 1766 case Variable::PARAMETER: |
1702 case Variable::LOCAL: { | 1767 case Variable::LOCAL: { |
1703 // Local var, const, or let variable. | 1768 // Local var, const, or let variable. |
1704 Node* value = environment()->Lookup(variable); | 1769 Node* value = environment()->Lookup(variable); |
1705 if (mode == CONST_LEGACY) { | 1770 if (mode == CONST_LEGACY) { |
1706 // Perform check for uninitialized legacy const variables. | 1771 // Perform check for uninitialized legacy const variables. |
1707 if (value->op() == the_hole->op()) { | 1772 if (value->op() == the_hole->op()) { |
1708 value = jsgraph()->UndefinedConstant(); | 1773 value = jsgraph()->UndefinedConstant(); |
1709 } else if (value->opcode() == IrOpcode::kPhi) { | 1774 } 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); | 1843 Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); |
1779 return NewNode(op, current_context(), name); | 1844 return NewNode(op, current_context(), name); |
1780 } | 1845 } |
1781 } | 1846 } |
1782 UNREACHABLE(); | 1847 UNREACHABLE(); |
1783 return NULL; | 1848 return NULL; |
1784 } | 1849 } |
1785 | 1850 |
1786 | 1851 |
1787 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, | 1852 Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, |
1788 Token::Value op) { | 1853 Token::Value op, |
| 1854 BailoutId bailout_id) { |
1789 Node* the_hole = jsgraph()->TheHoleConstant(); | 1855 Node* the_hole = jsgraph()->TheHoleConstant(); |
1790 VariableMode mode = variable->mode(); | 1856 VariableMode mode = variable->mode(); |
1791 switch (variable->location()) { | 1857 switch (variable->location()) { |
1792 case Variable::UNALLOCATED: { | 1858 case Variable::UNALLOCATED: { |
1793 // Global var, const, or let variable. | 1859 // Global var, const, or let variable. |
1794 Node* global = BuildLoadGlobalObject(); | 1860 Node* global = BuildLoadGlobalObject(); |
1795 PrintableUnique<Name> name = MakeUnique(variable->name()); | 1861 PrintableUnique<Name> name = MakeUnique(variable->name()); |
1796 Operator* op = javascript()->StoreNamed(name); | 1862 Operator* op = javascript()->StoreNamed(name); |
1797 return NewNode(op, global, value); | 1863 Node* store = NewNode(op, global, value); |
| 1864 BuildLazyBailout(store, bailout_id); |
| 1865 return store; |
1798 } | 1866 } |
1799 case Variable::PARAMETER: | 1867 case Variable::PARAMETER: |
1800 case Variable::LOCAL: | 1868 case Variable::LOCAL: |
1801 // Local var, const, or let variable. | 1869 // Local var, const, or let variable. |
1802 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { | 1870 if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) { |
1803 // Perform an initialization check for legacy const variables. | 1871 // Perform an initialization check for legacy const variables. |
1804 Node* current = environment()->Lookup(variable); | 1872 Node* current = environment()->Lookup(variable); |
1805 if (current->op() != the_hole->op()) { | 1873 if (current->op() != the_hole->op()) { |
1806 value = BuildHoleCheckSilent(current, value, current); | 1874 value = BuildHoleCheckSilent(current, value, current); |
1807 } | 1875 } |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 DCHECK(environment()->GetControlDependency() == node); | 2019 DCHECK(environment()->GetControlDependency() == node); |
1952 | 2020 |
1953 StructuredGraphBuilder::Environment* continuation_env = environment(); | 2021 StructuredGraphBuilder::Environment* continuation_env = environment(); |
1954 // Create environment for the deoptimization block, and build the block. | 2022 // Create environment for the deoptimization block, and build the block. |
1955 StructuredGraphBuilder::Environment* deopt_env = | 2023 StructuredGraphBuilder::Environment* deopt_env = |
1956 CopyEnvironment(continuation_env); | 2024 CopyEnvironment(continuation_env); |
1957 set_environment(deopt_env); | 2025 set_environment(deopt_env); |
1958 | 2026 |
1959 NewNode(common()->LazyDeoptimization()); | 2027 NewNode(common()->LazyDeoptimization()); |
1960 | 2028 |
| 2029 // TODO(jarin) If ast_id.IsNone(), perhaps we should generate an empty |
| 2030 // deopt block and make sure there is no patch entry for this (so |
| 2031 // that the deoptimizer dies when trying to deoptimize here). |
| 2032 |
1961 Node* state_node = environment()->Checkpoint(ast_id); | 2033 Node* state_node = environment()->Checkpoint(ast_id); |
1962 | 2034 |
1963 Node* deoptimize_node = NewNode(common()->Deoptimize(), state_node); | 2035 Node* deoptimize_node = NewNode(common()->Deoptimize(), state_node); |
1964 | 2036 |
1965 UpdateControlDependencyToLeaveFunction(deoptimize_node); | 2037 UpdateControlDependencyToLeaveFunction(deoptimize_node); |
1966 | 2038 |
1967 // Continue with the original environment. | 2039 // Continue with the original environment. |
1968 set_environment(continuation_env); | 2040 set_environment(continuation_env); |
1969 | 2041 |
1970 NewNode(common()->Continuation()); | 2042 NewNode(common()->Continuation()); |
1971 } | 2043 } |
1972 } | 2044 } |
| 2045 |
| 2046 |
| 2047 void AstGraphBuilder::BuildLazyBailoutWithPushedNode(Node* node, |
| 2048 BailoutId ast_id) { |
| 2049 environment()->Push(node); |
| 2050 BuildLazyBailout(node, ast_id); |
| 2051 environment()->Pop(); |
| 2052 } |
1973 } | 2053 } |
1974 } | 2054 } |
1975 } // namespace v8::internal::compiler | 2055 } // namespace v8::internal::compiler |
OLD | NEW |