| 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" |
| 11 #include "src/deoptimizer.h" | 11 #include "src/deoptimizer.h" |
| 12 #include "src/frames-inl.h" | 12 #include "src/frames-inl.h" |
| 13 #include "src/isolate-inl.h" | 13 #include "src/isolate-inl.h" |
| 14 #include "src/messages.h" | 14 #include "src/messages.h" |
| 15 | 15 |
| 16 namespace v8 { | 16 namespace v8 { |
| 17 namespace internal { | 17 namespace internal { |
| 18 | 18 |
| 19 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { |
| 20 HandleScope scope(isolate); |
| 21 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
| 22 NewTypeError(MessageTemplate::kConstAssign)); |
| 23 } |
| 24 |
| 25 namespace { |
| 26 |
| 19 enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 }; | 27 enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 }; |
| 20 | 28 |
| 21 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name, | 29 Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name, |
| 22 RedeclarationType redeclaration_type) { | 30 RedeclarationType redeclaration_type) { |
| 23 HandleScope scope(isolate); | 31 HandleScope scope(isolate); |
| 24 if (redeclaration_type == RedeclarationType::kSyntaxError) { | 32 if (redeclaration_type == RedeclarationType::kSyntaxError) { |
| 25 THROW_NEW_ERROR_RETURN_FAILURE( | 33 THROW_NEW_ERROR_RETURN_FAILURE( |
| 26 isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name)); | 34 isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name)); |
| 27 } else { | 35 } else { |
| 28 THROW_NEW_ERROR_RETURN_FAILURE( | 36 THROW_NEW_ERROR_RETURN_FAILURE( |
| 29 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); | 37 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); |
| 30 } | 38 } |
| 31 } | 39 } |
| 32 | 40 |
| 33 | 41 |
| 34 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { | |
| 35 HandleScope scope(isolate); | |
| 36 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | |
| 37 NewTypeError(MessageTemplate::kConstAssign)); | |
| 38 } | |
| 39 | |
| 40 | |
| 41 // May throw a RedeclarationError. | 42 // May throw a RedeclarationError. |
| 42 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, | 43 Object* DeclareGlobal( |
| 43 Handle<String> name, Handle<Object> value, | 44 Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name, |
| 44 PropertyAttributes attr, bool is_var, | 45 Handle<Object> value, PropertyAttributes attr, bool is_var, |
| 45 bool is_function, | 46 bool is_function, RedeclarationType redeclaration_type, |
| 46 RedeclarationType redeclaration_type) { | 47 Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>(), |
| 48 FeedbackVectorSlot slot = FeedbackVectorSlot::Invalid()) { |
| 47 Handle<ScriptContextTable> script_contexts( | 49 Handle<ScriptContextTable> script_contexts( |
| 48 global->native_context()->script_context_table()); | 50 global->native_context()->script_context_table()); |
| 49 ScriptContextTable::LookupResult lookup; | 51 ScriptContextTable::LookupResult lookup; |
| 50 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && | 52 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && |
| 51 IsLexicalVariableMode(lookup.mode)) { | 53 IsLexicalVariableMode(lookup.mode)) { |
| 52 // ES#sec-globaldeclarationinstantiation 6.a: | 54 // ES#sec-globaldeclarationinstantiation 6.a: |
| 53 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError | 55 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError |
| 54 // exception. | 56 // exception. |
| 55 return ThrowRedeclarationError(isolate, name, | 57 return ThrowRedeclarationError(isolate, name, |
| 56 RedeclarationType::kSyntaxError); | 58 RedeclarationType::kSyntaxError); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 // 'function onload() {}' would invalidly register that function as the | 98 // 'function onload() {}' would invalidly register that function as the |
| 97 // onload callback. To avoid this situation, we first delete the property | 99 // onload callback. To avoid this situation, we first delete the property |
| 98 // before readding it as a regular data property below. | 100 // before readding it as a regular data property below. |
| 99 if (it.state() == LookupIterator::ACCESSOR) it.Delete(); | 101 if (it.state() == LookupIterator::ACCESSOR) it.Delete(); |
| 100 } | 102 } |
| 101 | 103 |
| 102 // Define or redefine own property. | 104 // Define or redefine own property. |
| 103 RETURN_FAILURE_ON_EXCEPTION( | 105 RETURN_FAILURE_ON_EXCEPTION( |
| 104 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr)); | 106 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr)); |
| 105 | 107 |
| 108 if (!feedback_vector.is_null()) { |
| 109 DCHECK_EQ(*global, *it.GetHolder<Object>()); |
| 110 // Preinitialize the feedback slot if the global object does not have |
| 111 // named interceptor or the interceptor is not masking. |
| 112 if (!global->HasNamedInterceptor() || |
| 113 global->GetNamedInterceptor()->non_masking()) { |
| 114 LoadGlobalICNexus nexus(feedback_vector, slot); |
| 115 nexus.ConfigurePropertyCellMode(it.GetPropertyCell()); |
| 116 } |
| 117 } |
| 106 return isolate->heap()->undefined_value(); | 118 return isolate->heap()->undefined_value(); |
| 107 } | 119 } |
| 108 | 120 |
| 109 | 121 Object* DeclareGlobals(Isolate* isolate, Handle<FixedArray> pairs, int flags, |
| 110 RUNTIME_FUNCTION(Runtime_DeclareGlobals) { | 122 Handle<TypeFeedbackVector> feedback_vector) { |
| 111 HandleScope scope(isolate); | 123 HandleScope scope(isolate); |
| 112 DCHECK_EQ(2, args.length()); | |
| 113 Handle<JSGlobalObject> global(isolate->global_object()); | 124 Handle<JSGlobalObject> global(isolate->global_object()); |
| 114 Handle<Context> context(isolate->context()); | 125 Handle<Context> context(isolate->context()); |
| 115 | 126 |
| 116 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); | |
| 117 CONVERT_SMI_ARG_CHECKED(flags, 1); | |
| 118 | |
| 119 // Traverse the name/value pairs and set the properties. | 127 // Traverse the name/value pairs and set the properties. |
| 120 int length = pairs->length(); | 128 int length = pairs->length(); |
| 121 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, { | 129 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, { |
| 122 Handle<String> name(String::cast(pairs->get(i))); | 130 FeedbackVectorSlot slot(Smi::cast(pairs->get(i))->value()); |
| 131 Handle<String> name(feedback_vector->GetName(slot), isolate); |
| 123 Handle<Object> initial_value(pairs->get(i + 1), isolate); | 132 Handle<Object> initial_value(pairs->get(i + 1), isolate); |
| 124 | 133 |
| 125 bool is_var = initial_value->IsUndefined(isolate); | 134 bool is_var = initial_value->IsUndefined(isolate); |
| 126 bool is_function = initial_value->IsSharedFunctionInfo(); | 135 bool is_function = initial_value->IsSharedFunctionInfo(); |
| 127 DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function)); | 136 DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function)); |
| 128 | 137 |
| 129 Handle<Object> value; | 138 Handle<Object> value; |
| 130 if (is_function) { | 139 if (is_function) { |
| 131 // Copy the function and update its context. Use it as value. | 140 // Copy the function and update its context. Use it as value. |
| 132 Handle<SharedFunctionInfo> shared = | 141 Handle<SharedFunctionInfo> shared = |
| 133 Handle<SharedFunctionInfo>::cast(initial_value); | 142 Handle<SharedFunctionInfo>::cast(initial_value); |
| 134 Handle<JSFunction> function = | 143 Handle<JSFunction> function = |
| 135 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, | 144 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, |
| 136 TENURED); | 145 TENURED); |
| 137 value = function; | 146 value = function; |
| 138 } else { | 147 } else { |
| 139 value = isolate->factory()->undefined_value(); | 148 value = isolate->factory()->undefined_value(); |
| 140 } | 149 } |
| 141 | 150 |
| 142 // Compute the property attributes. According to ECMA-262, | 151 // Compute the property attributes. According to ECMA-262, |
| 143 // the property must be non-configurable except in eval. | 152 // the property must be non-configurable except in eval. |
| 144 bool is_native = DeclareGlobalsNativeFlag::decode(flags); | 153 bool is_native = DeclareGlobalsNativeFlag::decode(flags); |
| 145 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); | 154 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); |
| 146 int attr = NONE; | 155 int attr = NONE; |
| 147 if (is_function && is_native) attr |= READ_ONLY; | 156 if (is_function && is_native) attr |= READ_ONLY; |
| 148 if (!is_eval) attr |= DONT_DELETE; | 157 if (!is_eval) attr |= DONT_DELETE; |
| 149 | 158 |
| 150 // ES#sec-globaldeclarationinstantiation 5.d: | 159 // ES#sec-globaldeclarationinstantiation 5.d: |
| 151 // If hasRestrictedGlobal is true, throw a SyntaxError exception. | 160 // If hasRestrictedGlobal is true, throw a SyntaxError exception. |
| 152 Object* result = DeclareGlobals( | 161 Object* result = DeclareGlobal( |
| 153 isolate, global, name, value, static_cast<PropertyAttributes>(attr), | 162 isolate, global, name, value, static_cast<PropertyAttributes>(attr), |
| 154 is_var, is_function, RedeclarationType::kSyntaxError); | 163 is_var, is_function, RedeclarationType::kSyntaxError, feedback_vector, |
| 164 slot); |
| 155 if (isolate->has_pending_exception()) return result; | 165 if (isolate->has_pending_exception()) return result; |
| 156 }); | 166 }); |
| 157 | 167 |
| 158 return isolate->heap()->undefined_value(); | 168 return isolate->heap()->undefined_value(); |
| 159 } | 169 } |
| 160 | 170 |
| 171 } // namespace |
| 172 |
| 173 RUNTIME_FUNCTION(Runtime_DeclareGlobals) { |
| 174 HandleScope scope(isolate); |
| 175 DCHECK_EQ(3, args.length()); |
| 176 |
| 177 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); |
| 178 CONVERT_SMI_ARG_CHECKED(flags, 1); |
| 179 CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, feedback_vector, 2); |
| 180 |
| 181 return DeclareGlobals(isolate, pairs, flags, feedback_vector); |
| 182 } |
| 183 |
| 184 // TODO(ishell): merge this with Runtime::kDeclareGlobals once interpreter |
| 185 // is able to pass feedback vector. |
| 186 RUNTIME_FUNCTION(Runtime_DeclareGlobalsForInterpreter) { |
| 187 HandleScope scope(isolate); |
| 188 DCHECK_EQ(3, args.length()); |
| 189 |
| 190 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); |
| 191 CONVERT_SMI_ARG_CHECKED(flags, 1); |
| 192 CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 2); |
| 193 |
| 194 Handle<TypeFeedbackVector> feedback_vector(closure->feedback_vector(), |
| 195 isolate); |
| 196 return DeclareGlobals(isolate, pairs, flags, feedback_vector); |
| 197 } |
| 161 | 198 |
| 162 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { | 199 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { |
| 163 HandleScope scope(isolate); | 200 HandleScope scope(isolate); |
| 164 DCHECK_EQ(3, args.length()); | 201 DCHECK_EQ(3, args.length()); |
| 165 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 202 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 166 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1); | 203 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1); |
| 167 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | 204 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); |
| 168 | 205 |
| 169 Handle<JSGlobalObject> global(isolate->context()->global_object()); | 206 Handle<JSGlobalObject> global(isolate->global_object()); |
| 170 RETURN_RESULT_OR_FAILURE( | 207 RETURN_RESULT_OR_FAILURE( |
| 171 isolate, Object::SetProperty(global, name, value, language_mode)); | 208 isolate, Object::SetProperty(global, name, value, language_mode)); |
| 172 } | 209 } |
| 173 | 210 |
| 174 | 211 |
| 175 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) { | 212 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) { |
| 176 HandleScope handle_scope(isolate); | 213 HandleScope handle_scope(isolate); |
| 177 DCHECK_EQ(2, args.length()); | 214 DCHECK_EQ(2, args.length()); |
| 178 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 215 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 179 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 216 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 180 | 217 |
| 181 Handle<JSGlobalObject> global = isolate->global_object(); | 218 Handle<JSGlobalObject> global(isolate->global_object()); |
| 182 | 219 |
| 183 // Lookup the property as own on the global object. | 220 // Lookup the property as own on the global object. |
| 184 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); | 221 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 185 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 222 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 186 DCHECK(maybe.IsJust()); | 223 DCHECK(maybe.IsJust()); |
| 187 PropertyAttributes old_attributes = maybe.FromJust(); | 224 PropertyAttributes old_attributes = maybe.FromJust(); |
| 188 | 225 |
| 189 PropertyAttributes attr = | 226 PropertyAttributes attr = |
| 190 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 227 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
| 191 // Set the value if the property is either missing, or the property attributes | 228 // Set the value if the property is either missing, or the property attributes |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 | 281 |
| 245 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, | 282 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, |
| 246 &attributes, &binding_flags); | 283 &attributes, &binding_flags); |
| 247 DCHECK(!isolate->has_pending_exception()); | 284 DCHECK(!isolate->has_pending_exception()); |
| 248 | 285 |
| 249 Handle<JSObject> object; | 286 Handle<JSObject> object; |
| 250 | 287 |
| 251 if (attributes != ABSENT && holder->IsJSGlobalObject()) { | 288 if (attributes != ABSENT && holder->IsJSGlobalObject()) { |
| 252 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: | 289 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: |
| 253 // If fnDefinable is false, throw a TypeError exception. | 290 // If fnDefinable is false, throw a TypeError exception. |
| 254 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, | 291 return DeclareGlobal(isolate, Handle<JSGlobalObject>::cast(holder), name, |
| 255 value, NONE, is_var, is_function, | 292 value, NONE, is_var, is_function, |
| 256 RedeclarationType::kTypeError); | 293 RedeclarationType::kTypeError); |
| 257 } | 294 } |
| 258 if (context_arg->extension()->IsJSGlobalObject()) { | 295 if (context_arg->extension()->IsJSGlobalObject()) { |
| 259 Handle<JSGlobalObject> global( | 296 Handle<JSGlobalObject> global( |
| 260 JSGlobalObject::cast(context_arg->extension()), isolate); | 297 JSGlobalObject::cast(context_arg->extension()), isolate); |
| 261 return DeclareGlobals(isolate, global, name, value, NONE, is_var, | 298 return DeclareGlobal(isolate, global, name, value, NONE, is_var, |
| 262 is_function, RedeclarationType::kTypeError); | 299 is_function, RedeclarationType::kTypeError); |
| 263 } else if (context->IsScriptContext()) { | 300 } else if (context->IsScriptContext()) { |
| 264 DCHECK(context->global_object()->IsJSGlobalObject()); | 301 DCHECK(context->global_object()->IsJSGlobalObject()); |
| 265 Handle<JSGlobalObject> global( | 302 Handle<JSGlobalObject> global( |
| 266 JSGlobalObject::cast(context->global_object()), isolate); | 303 JSGlobalObject::cast(context->global_object()), isolate); |
| 267 return DeclareGlobals(isolate, global, name, value, NONE, is_var, | 304 return DeclareGlobal(isolate, global, name, value, NONE, is_var, |
| 268 is_function, RedeclarationType::kTypeError); | 305 is_function, RedeclarationType::kTypeError); |
| 269 } | 306 } |
| 270 | 307 |
| 271 if (attributes != ABSENT) { | 308 if (attributes != ABSENT) { |
| 272 DCHECK_EQ(NONE, attributes); | 309 DCHECK_EQ(NONE, attributes); |
| 273 | 310 |
| 274 // Skip var re-declarations. | 311 // Skip var re-declarations. |
| 275 if (is_var) return isolate->heap()->undefined_value(); | 312 if (is_var) return isolate->heap()->undefined_value(); |
| 276 | 313 |
| 277 DCHECK(is_function); | 314 DCHECK(is_function); |
| 278 if (index != Context::kNotFound) { | 315 if (index != Context::kNotFound) { |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { | 972 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { |
| 936 HandleScope scope(isolate); | 973 HandleScope scope(isolate); |
| 937 DCHECK_EQ(2, args.length()); | 974 DCHECK_EQ(2, args.length()); |
| 938 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 975 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
| 939 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 976 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 940 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); | 977 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); |
| 941 } | 978 } |
| 942 | 979 |
| 943 } // namespace internal | 980 } // namespace internal |
| 944 } // namespace v8 | 981 } // namespace v8 |
| OLD | NEW |