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/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/ast/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" |
10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 } | 925 } |
926 } | 926 } |
927 | 927 |
928 DCHECK(!isolate->has_pending_exception()); | 928 DCHECK(!isolate->has_pending_exception()); |
929 return isolate->heap()->undefined_value(); | 929 return isolate->heap()->undefined_value(); |
930 } | 930 } |
931 | 931 |
932 | 932 |
933 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) { | 933 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) { |
934 HandleScope scope(isolate); | 934 HandleScope scope(isolate); |
935 DCHECK(args.length() == 2); | 935 DCHECK_EQ(1, args.length()); |
936 | 936 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
937 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0); | |
938 CONVERT_ARG_HANDLE_CHECKED(String, name, 1); | |
939 | 937 |
940 int index; | 938 int index; |
941 PropertyAttributes attributes; | 939 PropertyAttributes attributes; |
942 ContextLookupFlags flags = FOLLOW_CHAINS; | 940 BindingFlags flags; |
943 BindingFlags binding_flags; | 941 Handle<Object> holder = isolate->context()->Lookup( |
944 Handle<Object> holder = | 942 name, FOLLOW_CHAINS, &index, &attributes, &flags); |
945 context->Lookup(name, flags, &index, &attributes, &binding_flags); | |
946 | 943 |
947 // If the slot was not found the result is true. | 944 // If the slot was not found the result is true. |
948 if (holder.is_null()) { | 945 if (holder.is_null()) { |
949 // In case of JSProxy, an exception might have been thrown. | 946 // In case of JSProxy, an exception might have been thrown. |
950 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 947 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
951 return isolate->heap()->true_value(); | 948 return isolate->heap()->true_value(); |
952 } | 949 } |
953 | 950 |
954 // If the slot was found in a context, it should be DONT_DELETE. | 951 // If the slot was found in a context, it should be DONT_DELETE. |
955 if (holder->IsContext()) { | 952 if (holder->IsContext()) { |
956 return isolate->heap()->false_value(); | 953 return isolate->heap()->false_value(); |
957 } | 954 } |
958 | 955 |
959 // The slot was found in a JSReceiver, either a context extension object, | 956 // The slot was found in a JSReceiver, either a context extension object, |
960 // the global object, or the subject of a with. Try to delete it | 957 // the global object, or the subject of a with. Try to delete it |
961 // (respecting DONT_DELETE). | 958 // (respecting DONT_DELETE). |
962 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); | 959 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); |
963 Maybe<bool> result = JSReceiver::DeleteProperty(object, name); | 960 Maybe<bool> result = JSReceiver::DeleteProperty(object, name); |
964 MAYBE_RETURN(result, isolate->heap()->exception()); | 961 MAYBE_RETURN(result, isolate->heap()->exception()); |
965 return isolate->heap()->ToBoolean(result.FromJust()); | 962 return isolate->heap()->ToBoolean(result.FromJust()); |
966 } | 963 } |
967 | 964 |
968 | 965 |
969 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, JSObject* holder) { | 966 namespace { |
970 DCHECK(!holder->IsJSGlobalObject()); | |
971 | 967 |
972 // If the holder isn't a context extension object, we just return it | 968 MaybeHandle<Object> LoadLookupSlot(Handle<String> name, |
973 // as the receiver. This allows arguments objects to be used as | 969 Object::ShouldThrow should_throw, |
974 // receivers, but only if they are put in the context scope chain | 970 Handle<Object>* receiver_return = nullptr) { |
975 // explicitly via a with-statement. | 971 Isolate* const isolate = name->GetIsolate(); |
976 if (holder->map()->instance_type() != JS_CONTEXT_EXTENSION_OBJECT_TYPE) { | |
977 return holder; | |
978 } | |
979 // Fall back to using the global object as the implicit receiver if | |
980 // the property turns out to be a local variable allocated in a | |
981 // context extension object - introduced via eval. | |
982 return isolate->heap()->undefined_value(); | |
983 } | |
984 | |
985 | |
986 static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate, | |
987 bool throw_error) { | |
988 HandleScope scope(isolate); | |
989 DCHECK_EQ(2, args.length()); | |
990 | |
991 if (!args[0]->IsContext() || !args[1]->IsString()) { | |
992 return MakePair(isolate->ThrowIllegalOperation(), NULL); | |
993 } | |
994 Handle<Context> context = args.at<Context>(0); | |
995 Handle<String> name = args.at<String>(1); | |
996 | 972 |
997 int index; | 973 int index; |
998 PropertyAttributes attributes; | 974 PropertyAttributes attributes; |
999 ContextLookupFlags flags = FOLLOW_CHAINS; | 975 BindingFlags flags; |
1000 BindingFlags binding_flags; | 976 Handle<Object> holder = isolate->context()->Lookup( |
1001 Handle<Object> holder = | 977 name, FOLLOW_CHAINS, &index, &attributes, &flags); |
1002 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 978 if (isolate->has_pending_exception()) return MaybeHandle<Object>(); |
1003 if (isolate->has_pending_exception()) { | |
1004 return MakePair(isolate->heap()->exception(), NULL); | |
1005 } | |
1006 | 979 |
1007 if (index != Context::kNotFound) { | 980 if (index != Context::kNotFound) { |
1008 DCHECK(holder->IsContext()); | 981 DCHECK(holder->IsContext()); |
1009 // If the "property" we were looking for is a local variable, the | 982 // If the "property" we were looking for is a local variable, the |
1010 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3. | 983 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3. |
1011 Handle<Object> receiver = isolate->factory()->undefined_value(); | 984 Handle<Object> receiver = isolate->factory()->undefined_value(); |
1012 Object* value = Context::cast(*holder)->get(index); | 985 Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate); |
1013 // Check for uninitialized bindings. | 986 // Check for uninitialized bindings. |
1014 switch (binding_flags) { | 987 switch (flags) { |
1015 case MUTABLE_CHECK_INITIALIZED: | 988 case MUTABLE_CHECK_INITIALIZED: |
1016 case IMMUTABLE_CHECK_INITIALIZED_HARMONY: | 989 case IMMUTABLE_CHECK_INITIALIZED_HARMONY: |
1017 if (value->IsTheHole()) { | 990 if (value->IsTheHole()) { |
1018 Handle<Object> error = isolate->factory()->NewReferenceError( | 991 THROW_NEW_ERROR(isolate, |
1019 MessageTemplate::kNotDefined, name); | 992 NewReferenceError(MessageTemplate::kNotDefined, name), |
1020 isolate->Throw(*error); | 993 Object); |
1021 return MakePair(isolate->heap()->exception(), NULL); | 994 } |
| 995 // FALLTHROUGH |
| 996 case IMMUTABLE_CHECK_INITIALIZED: |
| 997 if (value->IsTheHole()) { |
| 998 DCHECK(attributes & READ_ONLY); |
| 999 value = isolate->factory()->undefined_value(); |
1022 } | 1000 } |
1023 // FALLTHROUGH | 1001 // FALLTHROUGH |
1024 case MUTABLE_IS_INITIALIZED: | 1002 case MUTABLE_IS_INITIALIZED: |
1025 case IMMUTABLE_IS_INITIALIZED: | 1003 case IMMUTABLE_IS_INITIALIZED: |
1026 case IMMUTABLE_IS_INITIALIZED_HARMONY: | 1004 case IMMUTABLE_IS_INITIALIZED_HARMONY: |
1027 DCHECK(!value->IsTheHole()); | 1005 DCHECK(!value->IsTheHole()); |
1028 return MakePair(value, *receiver); | 1006 if (receiver_return) *receiver_return = receiver; |
1029 case IMMUTABLE_CHECK_INITIALIZED: | 1007 return value; |
1030 if (value->IsTheHole()) { | |
1031 DCHECK((attributes & READ_ONLY) != 0); | |
1032 value = isolate->heap()->undefined_value(); | |
1033 } | |
1034 return MakePair(value, *receiver); | |
1035 case MISSING_BINDING: | 1008 case MISSING_BINDING: |
1036 UNREACHABLE(); | 1009 break; |
1037 return MakePair(NULL, NULL); | |
1038 } | 1010 } |
| 1011 UNREACHABLE(); |
1039 } | 1012 } |
1040 | 1013 |
1041 // Otherwise, if the slot was found the holder is a context extension | 1014 // Otherwise, if the slot was found the holder is a context extension |
1042 // object, subject of a with, or a global object. We read the named | 1015 // object, subject of a with, or a global object. We read the named |
1043 // property from it. | 1016 // property from it. |
1044 if (!holder.is_null()) { | 1017 if (!holder.is_null()) { |
1045 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); | |
1046 // GetProperty below can cause GC. | |
1047 Handle<Object> receiver_handle( | |
1048 object->IsJSGlobalObject() | |
1049 ? Object::cast(isolate->heap()->undefined_value()) | |
1050 : object->IsJSProxy() ? static_cast<Object*>(*object) | |
1051 : ComputeReceiverForNonGlobal( | |
1052 isolate, JSObject::cast(*object)), | |
1053 isolate); | |
1054 | |
1055 // No need to unhole the value here. This is taken care of by the | 1018 // No need to unhole the value here. This is taken care of by the |
1056 // GetProperty function. | 1019 // GetProperty function. |
1057 Handle<Object> value; | 1020 Handle<Object> value; |
1058 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1021 ASSIGN_RETURN_ON_EXCEPTION( |
1059 isolate, value, Object::GetProperty(object, name), | 1022 isolate, value, Object::GetProperty(holder, name), |
1060 MakePair(isolate->heap()->exception(), NULL)); | 1023 Object); |
1061 return MakePair(*value, *receiver_handle); | 1024 if (receiver_return) { |
| 1025 *receiver_return = |
| 1026 (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject()) |
| 1027 ? Handle<Object>::cast(isolate->factory()->undefined_value()) |
| 1028 : holder; |
| 1029 } |
| 1030 return value; |
1062 } | 1031 } |
1063 | 1032 |
1064 if (throw_error) { | 1033 if (should_throw == Object::THROW_ON_ERROR) { |
1065 // The property doesn't exist - throw exception. | 1034 // The property doesn't exist - throw exception. |
1066 Handle<Object> error = isolate->factory()->NewReferenceError( | 1035 THROW_NEW_ERROR( |
1067 MessageTemplate::kNotDefined, name); | 1036 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object); |
1068 isolate->Throw(*error); | |
1069 return MakePair(isolate->heap()->exception(), NULL); | |
1070 } else { | |
1071 // The property doesn't exist - return undefined. | |
1072 return MakePair(isolate->heap()->undefined_value(), | |
1073 isolate->heap()->undefined_value()); | |
1074 } | 1037 } |
| 1038 |
| 1039 // The property doesn't exist - return undefined. |
| 1040 if (receiver_return) *receiver_return = isolate->factory()->undefined_value(); |
| 1041 return isolate->factory()->undefined_value(); |
| 1042 } |
| 1043 |
| 1044 } // namespace |
| 1045 |
| 1046 |
| 1047 RUNTIME_FUNCTION(Runtime_LoadLookupSlot) { |
| 1048 HandleScope scope(isolate); |
| 1049 DCHECK_EQ(1, args.length()); |
| 1050 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 1051 Handle<Object> value; |
| 1052 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1053 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR)); |
| 1054 return *value; |
1075 } | 1055 } |
1076 | 1056 |
1077 | 1057 |
1078 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) { | 1058 RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) { |
1079 return LoadLookupSlotHelper(args, isolate, true); | 1059 HandleScope scope(isolate); |
| 1060 DCHECK_EQ(1, args.length()); |
| 1061 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 1062 Handle<Object> value; |
| 1063 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1064 isolate, value, LoadLookupSlot(name, Object::DONT_THROW)); |
| 1065 return *value; |
1080 } | 1066 } |
1081 | 1067 |
1082 | 1068 |
1083 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) { | 1069 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall) { |
1084 return LoadLookupSlotHelper(args, isolate, false); | 1070 HandleScope scope(isolate); |
| 1071 DCHECK_EQ(1, args.length()); |
| 1072 DCHECK(args[0]->IsString()); |
| 1073 Handle<String> name = args.at<String>(0); |
| 1074 Handle<Object> value; |
| 1075 Handle<Object> receiver; |
| 1076 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 1077 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR, &receiver), |
| 1078 MakePair(isolate->heap()->exception(), nullptr)); |
| 1079 return MakePair(*value, *receiver); |
1085 } | 1080 } |
1086 | 1081 |
1087 | 1082 |
1088 RUNTIME_FUNCTION(Runtime_StoreLookupSlot) { | 1083 namespace { |
1089 HandleScope scope(isolate); | |
1090 DCHECK(args.length() == 4); | |
1091 | 1084 |
1092 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); | 1085 MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value, |
1093 CONVERT_ARG_HANDLE_CHECKED(Context, context, 1); | 1086 LanguageMode language_mode) { |
1094 CONVERT_ARG_HANDLE_CHECKED(String, name, 2); | 1087 Isolate* const isolate = name->GetIsolate(); |
1095 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3); | 1088 Handle<Context> context(isolate->context(), isolate); |
1096 | 1089 |
1097 int index; | 1090 int index; |
1098 PropertyAttributes attributes; | 1091 PropertyAttributes attributes; |
1099 ContextLookupFlags flags = FOLLOW_CHAINS; | 1092 BindingFlags flags; |
1100 BindingFlags binding_flags; | |
1101 Handle<Object> holder = | 1093 Handle<Object> holder = |
1102 context->Lookup(name, flags, &index, &attributes, &binding_flags); | 1094 context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flags); |
1103 if (holder.is_null()) { | 1095 if (holder.is_null()) { |
1104 // In case of JSProxy, an exception might have been thrown. | 1096 // In case of JSProxy, an exception might have been thrown. |
1105 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 1097 if (isolate->has_pending_exception()) return MaybeHandle<Object>(); |
1106 } | 1098 } |
1107 | 1099 |
1108 // The property was found in a context slot. | 1100 // The property was found in a context slot. |
1109 if (index != Context::kNotFound) { | 1101 if (index != Context::kNotFound) { |
1110 if ((binding_flags == MUTABLE_CHECK_INITIALIZED || | 1102 if ((flags == MUTABLE_CHECK_INITIALIZED || |
1111 binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) && | 1103 flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) && |
1112 Handle<Context>::cast(holder)->is_the_hole(index)) { | 1104 Handle<Context>::cast(holder)->is_the_hole(index)) { |
1113 THROW_NEW_ERROR_RETURN_FAILURE( | 1105 THROW_NEW_ERROR(isolate, |
1114 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); | 1106 NewReferenceError(MessageTemplate::kNotDefined, name), |
| 1107 Object); |
1115 } | 1108 } |
1116 if ((attributes & READ_ONLY) == 0) { | 1109 if ((attributes & READ_ONLY) == 0) { |
1117 Handle<Context>::cast(holder)->set(index, *value); | 1110 Handle<Context>::cast(holder)->set(index, *value); |
1118 } else if (is_strict(language_mode)) { | 1111 } else if (is_strict(language_mode)) { |
1119 // Setting read only property in strict mode. | 1112 // Setting read only property in strict mode. |
1120 THROW_NEW_ERROR_RETURN_FAILURE( | 1113 THROW_NEW_ERROR(isolate, |
1121 isolate, NewTypeError(MessageTemplate::kStrictCannotAssign, name)); | 1114 NewTypeError(MessageTemplate::kStrictCannotAssign, name), |
| 1115 Object); |
1122 } | 1116 } |
1123 return *value; | 1117 return value; |
1124 } | 1118 } |
1125 | 1119 |
1126 // Slow case: The property is not in a context slot. It is either in a | 1120 // Slow case: The property is not in a context slot. It is either in a |
1127 // context extension object, a property of the subject of a with, or a | 1121 // context extension object, a property of the subject of a with, or a |
1128 // property of the global object. | 1122 // property of the global object. |
1129 Handle<JSReceiver> object; | 1123 Handle<JSReceiver> object; |
1130 if (attributes != ABSENT) { | 1124 if (attributes != ABSENT) { |
1131 // The property exists on the holder. | 1125 // The property exists on the holder. |
1132 object = Handle<JSReceiver>::cast(holder); | 1126 object = Handle<JSReceiver>::cast(holder); |
1133 } else if (is_strict(language_mode)) { | 1127 } else if (is_strict(language_mode)) { |
1134 // If absent in strict mode: throw. | 1128 // If absent in strict mode: throw. |
1135 THROW_NEW_ERROR_RETURN_FAILURE( | 1129 THROW_NEW_ERROR( |
1136 isolate, NewReferenceError(MessageTemplate::kNotDefined, name)); | 1130 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object); |
1137 } else { | 1131 } else { |
1138 // If absent in sloppy mode: add the property to the global object. | 1132 // If absent in sloppy mode: add the property to the global object. |
1139 object = Handle<JSReceiver>(context->global_object()); | 1133 object = Handle<JSReceiver>(context->global_object()); |
1140 } | 1134 } |
1141 | 1135 |
1142 RETURN_FAILURE_ON_EXCEPTION( | 1136 ASSIGN_RETURN_ON_EXCEPTION( |
1143 isolate, Object::SetProperty(object, name, value, language_mode)); | 1137 isolate, value, Object::SetProperty(object, name, value, language_mode), |
| 1138 Object); |
| 1139 return value; |
| 1140 } |
1144 | 1141 |
| 1142 } // namespace |
| 1143 |
| 1144 |
| 1145 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) { |
| 1146 HandleScope scope(isolate); |
| 1147 DCHECK_EQ(2, args.length()); |
| 1148 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 1149 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 1150 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, |
| 1151 StoreLookupSlot(name, value, SLOPPY)); |
1145 return *value; | 1152 return *value; |
1146 } | 1153 } |
1147 | 1154 |
| 1155 |
| 1156 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { |
| 1157 HandleScope scope(isolate); |
| 1158 DCHECK_EQ(2, args.length()); |
| 1159 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 1160 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 1161 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, |
| 1162 StoreLookupSlot(name, value, STRICT)); |
| 1163 return *value; |
| 1164 } |
| 1165 |
1148 | 1166 |
1149 RUNTIME_FUNCTION(Runtime_ArgumentsLength) { | 1167 RUNTIME_FUNCTION(Runtime_ArgumentsLength) { |
1150 HandleScope scope(isolate); | 1168 HandleScope scope(isolate); |
1151 DCHECK(args.length() == 0); | 1169 DCHECK(args.length() == 0); |
1152 int argument_count = 0; | 1170 int argument_count = 0; |
1153 GetCallerArguments(isolate, &argument_count); | 1171 GetCallerArguments(isolate, &argument_count); |
1154 return Smi::FromInt(argument_count); | 1172 return Smi::FromInt(argument_count); |
1155 } | 1173 } |
1156 | 1174 |
1157 | 1175 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1223 | 1241 |
1224 // Lookup in the initial Object.prototype object. | 1242 // Lookup in the initial Object.prototype object. |
1225 Handle<Object> result; | 1243 Handle<Object> result; |
1226 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1244 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
1227 isolate, result, | 1245 isolate, result, |
1228 Object::GetProperty(isolate->initial_object_prototype(), key)); | 1246 Object::GetProperty(isolate->initial_object_prototype(), key)); |
1229 return *result; | 1247 return *result; |
1230 } | 1248 } |
1231 } // namespace internal | 1249 } // namespace internal |
1232 } // namespace v8 | 1250 } // namespace v8 |
OLD | NEW |