OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
6 | 6 |
7 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
10 #include "src/compiler/bytecode-branch-analysis.h" | 10 #include "src/compiler/bytecode-branch-analysis.h" |
(...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 | 889 |
890 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() { | 890 void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() { |
891 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF); | 891 BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF); |
892 } | 892 } |
893 | 893 |
894 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( | 894 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( |
895 uint32_t depth) { | 895 uint32_t depth) { |
896 // Output environment where the context has an extension | 896 // Output environment where the context has an extension |
897 Environment* slow_environment = nullptr; | 897 Environment* slow_environment = nullptr; |
898 | 898 |
899 DCHECK_GT(depth, 0u); | |
900 | |
901 // We only need to check up to the last-but-one depth, because the an eval in | 899 // We only need to check up to the last-but-one depth, because the an eval in |
902 // the same scope as the variable itself has no way of shadowing it. | 900 // the same scope as the variable itself has no way of shadowing it. |
903 for (uint32_t d = 0; d < depth; d++) { | 901 for (uint32_t d = 0; d < depth; d++) { |
904 Node* extension_slot = | 902 Node* extension_slot = |
905 NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false), | 903 NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false), |
906 environment()->Context()); | 904 environment()->Context()); |
907 | 905 |
908 Node* check_no_extension = | 906 Node* check_no_extension = |
909 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), | 907 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), |
910 extension_slot, jsgraph()->TheHoleConstant()); | 908 extension_slot, jsgraph()->TheHoleConstant()); |
(...skipping 13 matching lines...) Expand all Loading... |
924 } | 922 } |
925 | 923 |
926 { | 924 { |
927 set_environment(true_environment); | 925 set_environment(true_environment); |
928 NewIfTrue(); | 926 NewIfTrue(); |
929 // Do nothing on if there is no extension, eventually falling through to | 927 // Do nothing on if there is no extension, eventually falling through to |
930 // the fast path. | 928 // the fast path. |
931 } | 929 } |
932 } | 930 } |
933 | 931 |
934 DCHECK_NOT_NULL(slow_environment); | 932 // The depth can be zero, in which case no slow-path checks are built, and the |
| 933 // slow path environment can be null. |
| 934 DCHECK(depth == 0 || slow_environment != nullptr); |
935 | 935 |
936 return slow_environment; | 936 return slow_environment; |
937 } | 937 } |
938 | 938 |
939 void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) { | 939 void BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) { |
940 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); | 940 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); |
941 | 941 |
942 // Check if any context in the depth has an extension. | 942 // Check if any context in the depth has an extension. |
943 Environment* slow_environment = CheckContextExtensions(depth); | 943 Environment* slow_environment = CheckContextExtensions(depth); |
944 | 944 |
945 // Fast path, do a context load. | 945 // Fast path, do a context load. |
946 { | 946 { |
947 uint32_t slot_index = bytecode_iterator().GetIndexOperand(1); | 947 uint32_t slot_index = bytecode_iterator().GetIndexOperand(1); |
948 | 948 |
949 const Operator* op = javascript()->LoadContext(depth, slot_index, false); | 949 const Operator* op = javascript()->LoadContext(depth, slot_index, false); |
950 Node* context = environment()->Context(); | 950 Node* context = environment()->Context(); |
951 environment()->BindAccumulator(NewNode(op, context)); | 951 environment()->BindAccumulator(NewNode(op, context)); |
952 NewMerge(); | |
953 } | |
954 Environment* fast_environment = environment(); | |
955 | |
956 // Slow path, do a runtime load lookup. | |
957 set_environment(slow_environment); | |
958 { | |
959 FrameStateBeforeAndAfter states(this); | |
960 | |
961 Node* name = | |
962 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); | |
963 | |
964 const Operator* op = | |
965 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF | |
966 ? Runtime::kLoadLookupSlot | |
967 : Runtime::kLoadLookupSlotInsideTypeof); | |
968 Node* value = NewNode(op, name); | |
969 environment()->BindAccumulator(value, &states); | |
970 } | 952 } |
971 | 953 |
972 fast_environment->Merge(environment()); | 954 // Only build the slow path if there were any slow-path checks. |
973 set_environment(fast_environment); | 955 if (slow_environment != nullptr) { |
| 956 // Add a merge to the fast environment. |
| 957 NewMerge(); |
| 958 Environment* fast_environment = environment(); |
| 959 |
| 960 // Slow path, do a runtime load lookup. |
| 961 set_environment(slow_environment); |
| 962 { |
| 963 FrameStateBeforeAndAfter states(this); |
| 964 |
| 965 Node* name = jsgraph()->Constant( |
| 966 bytecode_iterator().GetConstantForIndexOperand(0)); |
| 967 |
| 968 const Operator* op = |
| 969 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF |
| 970 ? Runtime::kLoadLookupSlot |
| 971 : Runtime::kLoadLookupSlotInsideTypeof); |
| 972 Node* value = NewNode(op, name); |
| 973 environment()->BindAccumulator(value, &states); |
| 974 } |
| 975 |
| 976 fast_environment->Merge(environment()); |
| 977 set_environment(fast_environment); |
| 978 } |
974 } | 979 } |
975 | 980 |
976 void BytecodeGraphBuilder::VisitLdaLookupContextSlot() { | 981 void BytecodeGraphBuilder::VisitLdaLookupContextSlot() { |
977 BuildLdaLookupContextSlot(TypeofMode::NOT_INSIDE_TYPEOF); | 982 BuildLdaLookupContextSlot(TypeofMode::NOT_INSIDE_TYPEOF); |
978 } | 983 } |
979 | 984 |
980 void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() { | 985 void BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() { |
981 BuildLdaLookupContextSlot(TypeofMode::INSIDE_TYPEOF); | 986 BuildLdaLookupContextSlot(TypeofMode::INSIDE_TYPEOF); |
982 } | 987 } |
983 | 988 |
984 void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) { | 989 void BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) { |
985 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); | 990 uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); |
986 | 991 |
987 // Check if any context in the depth has an extension. | 992 // Check if any context in the depth has an extension. |
988 Environment* slow_environment = CheckContextExtensions(depth); | 993 Environment* slow_environment = CheckContextExtensions(depth); |
989 | 994 |
990 // Fast path, do a global load. | 995 // Fast path, do a global load. |
991 { | 996 { |
992 FrameStateBeforeAndAfter states(this); | 997 FrameStateBeforeAndAfter states(this); |
993 Node* node = | 998 Node* node = |
994 BuildLoadGlobal(bytecode_iterator().GetIndexOperand(1), typeof_mode); | 999 BuildLoadGlobal(bytecode_iterator().GetIndexOperand(1), typeof_mode); |
995 environment()->BindAccumulator(node, &states); | 1000 environment()->BindAccumulator(node, &states); |
996 | |
997 NewMerge(); | |
998 } | |
999 Environment* fast_environment = environment(); | |
1000 | |
1001 // Slow path, do a runtime load lookup. | |
1002 set_environment(slow_environment); | |
1003 { | |
1004 FrameStateBeforeAndAfter states(this); | |
1005 | |
1006 Node* name = | |
1007 jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); | |
1008 | |
1009 const Operator* op = | |
1010 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF | |
1011 ? Runtime::kLoadLookupSlot | |
1012 : Runtime::kLoadLookupSlotInsideTypeof); | |
1013 Node* value = NewNode(op, name); | |
1014 environment()->BindAccumulator(value, &states); | |
1015 } | 1001 } |
1016 | 1002 |
1017 fast_environment->Merge(environment()); | 1003 // Only build the slow path if there were any slow-path checks. |
1018 set_environment(fast_environment); | 1004 if (slow_environment != nullptr) { |
| 1005 // Add a merge to the fast environment. |
| 1006 NewMerge(); |
| 1007 Environment* fast_environment = environment(); |
| 1008 |
| 1009 // Slow path, do a runtime load lookup. |
| 1010 set_environment(slow_environment); |
| 1011 { |
| 1012 FrameStateBeforeAndAfter states(this); |
| 1013 |
| 1014 Node* name = jsgraph()->Constant( |
| 1015 bytecode_iterator().GetConstantForIndexOperand(0)); |
| 1016 |
| 1017 const Operator* op = |
| 1018 javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF |
| 1019 ? Runtime::kLoadLookupSlot |
| 1020 : Runtime::kLoadLookupSlotInsideTypeof); |
| 1021 Node* value = NewNode(op, name); |
| 1022 environment()->BindAccumulator(value, &states); |
| 1023 } |
| 1024 |
| 1025 fast_environment->Merge(environment()); |
| 1026 set_environment(fast_environment); |
| 1027 } |
1019 } | 1028 } |
1020 | 1029 |
1021 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() { | 1030 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() { |
1022 BuildLdaLookupGlobalSlot(TypeofMode::NOT_INSIDE_TYPEOF); | 1031 BuildLdaLookupGlobalSlot(TypeofMode::NOT_INSIDE_TYPEOF); |
1023 } | 1032 } |
1024 | 1033 |
1025 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() { | 1034 void BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() { |
1026 BuildLdaLookupGlobalSlot(TypeofMode::INSIDE_TYPEOF); | 1035 BuildLdaLookupGlobalSlot(TypeofMode::INSIDE_TYPEOF); |
1027 } | 1036 } |
1028 | 1037 |
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2225 // Phi does not exist yet, introduce one. | 2234 // Phi does not exist yet, introduce one. |
2226 value = NewPhi(inputs, value, control); | 2235 value = NewPhi(inputs, value, control); |
2227 value->ReplaceInput(inputs - 1, other); | 2236 value->ReplaceInput(inputs - 1, other); |
2228 } | 2237 } |
2229 return value; | 2238 return value; |
2230 } | 2239 } |
2231 | 2240 |
2232 } // namespace compiler | 2241 } // namespace compiler |
2233 } // namespace internal | 2242 } // namespace internal |
2234 } // namespace v8 | 2243 } // namespace v8 |
OLD | NEW |