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