diff options
Diffstat (limited to 'deps/v8/src/runtime/runtime-scopes.cc')
-rw-r--r-- | deps/v8/src/runtime/runtime-scopes.cc | 557 |
1 files changed, 178 insertions, 379 deletions
diff --git a/deps/v8/src/runtime/runtime-scopes.cc b/deps/v8/src/runtime/runtime-scopes.cc index 5f3cdf2682..26bfb29d93 100644 --- a/deps/v8/src/runtime/runtime-scopes.cc +++ b/deps/v8/src/runtime/runtime-scopes.cc @@ -4,9 +4,10 @@ #include "src/runtime/runtime-utils.h" +#include <memory> + #include "src/accessors.h" #include "src/arguments.h" -#include "src/ast/scopeinfo.h" #include "src/ast/scopes.h" #include "src/deoptimizer.h" #include "src/frames-inl.h" @@ -16,43 +17,56 @@ namespace v8 { namespace internal { -static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) { +RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { HandleScope scope(isolate); - THROW_NEW_ERROR_RETURN_FAILURE( - isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); + THROW_NEW_ERROR_RETURN_FAILURE(isolate, + NewTypeError(MessageTemplate::kConstAssign)); } +namespace { -RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) { +enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 }; + +Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name, + RedeclarationType redeclaration_type) { HandleScope scope(isolate); - THROW_NEW_ERROR_RETURN_FAILURE(isolate, - NewTypeError(MessageTemplate::kConstAssign)); + if (redeclaration_type == RedeclarationType::kSyntaxError) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name)); + } else { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name)); + } } // May throw a RedeclarationError. -static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, - Handle<String> name, Handle<Object> value, - PropertyAttributes attr, bool is_var, - bool is_const, bool is_function) { +Object* DeclareGlobal( + Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name, + Handle<Object> value, PropertyAttributes attr, bool is_var, + bool is_function, RedeclarationType redeclaration_type, + Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>(), + FeedbackVectorSlot slot = FeedbackVectorSlot::Invalid()) { Handle<ScriptContextTable> script_contexts( global->native_context()->script_context_table()); ScriptContextTable::LookupResult lookup; if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && IsLexicalVariableMode(lookup.mode)) { - return ThrowRedeclarationError(isolate, name); + // ES#sec-globaldeclarationinstantiation 6.a: + // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError + // exception. + return ThrowRedeclarationError(isolate, name, + RedeclarationType::kSyntaxError); } // Do the lookup own properties only, see ES5 erratum. - LookupIterator it(global, name, global, - LookupIterator::HIDDEN_SKIP_INTERCEPTOR); + LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR); Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); if (!maybe.IsJust()) return isolate->heap()->exception(); if (it.IsFound()) { PropertyAttributes old_attributes = maybe.FromJust(); // The name was declared before; check for conflicting re-declarations. - if (is_const) return ThrowRedeclarationError(isolate, name); // Skip var re-declarations. if (is_var) return isolate->heap()->undefined_value(); @@ -69,7 +83,11 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, if (old_details.IsReadOnly() || old_details.IsDontEnum() || (it.state() == LookupIterator::ACCESSOR && it.GetAccessors()->IsAccessorPair())) { - return ThrowRedeclarationError(isolate, name); + // ES#sec-globaldeclarationinstantiation 5.d: + // If hasRestrictedGlobal is true, throw a SyntaxError exception. + // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: + // If fnDefinable is false, throw a TypeError exception. + return ThrowRedeclarationError(isolate, name, redeclaration_type); } // If the existing property is not configurable, keep its attributes. Do attr = old_attributes; @@ -88,33 +106,35 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global, RETURN_FAILURE_ON_EXCEPTION( isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr)); + if (!feedback_vector.is_null()) { + DCHECK_EQ(*global, *it.GetHolder<Object>()); + // Preinitialize the feedback slot if the global object does not have + // named interceptor or the interceptor is not masking. + if (!global->HasNamedInterceptor() || + global->GetNamedInterceptor()->non_masking()) { + LoadGlobalICNexus nexus(feedback_vector, slot); + nexus.ConfigurePropertyCellMode(it.GetPropertyCell()); + } + } return isolate->heap()->undefined_value(); } - -RUNTIME_FUNCTION(Runtime_DeclareGlobals) { +Object* DeclareGlobals(Isolate* isolate, Handle<FixedArray> pairs, int flags, + Handle<TypeFeedbackVector> feedback_vector) { HandleScope scope(isolate); - DCHECK_EQ(2, args.length()); Handle<JSGlobalObject> global(isolate->global_object()); Handle<Context> context(isolate->context()); - CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); - CONVERT_SMI_ARG_CHECKED(flags, 1); - // Traverse the name/value pairs and set the properties. int length = pairs->length(); FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, { - Handle<String> name(String::cast(pairs->get(i))); + FeedbackVectorSlot slot(Smi::cast(pairs->get(i))->value()); + Handle<String> name(feedback_vector->GetName(slot), isolate); Handle<Object> initial_value(pairs->get(i + 1), isolate); - // We have to declare a global const property. To capture we only - // assign to it when evaluating the assignment for "const x = - // <expr>" the initial value is the hole. - bool is_var = initial_value->IsUndefined(); - bool is_const = initial_value->IsTheHole(); + bool is_var = initial_value->IsUndefined(isolate); bool is_function = initial_value->IsSharedFunctionInfo(); - DCHECK_EQ(1, - BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function)); + DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function)); Handle<Object> value; if (is_function) { @@ -134,154 +154,126 @@ RUNTIME_FUNCTION(Runtime_DeclareGlobals) { bool is_native = DeclareGlobalsNativeFlag::decode(flags); bool is_eval = DeclareGlobalsEvalFlag::decode(flags); int attr = NONE; - if (is_const) attr |= READ_ONLY; if (is_function && is_native) attr |= READ_ONLY; - if (!is_const && !is_eval) attr |= DONT_DELETE; - - Object* result = DeclareGlobals(isolate, global, name, value, - static_cast<PropertyAttributes>(attr), - is_var, is_const, is_function); + if (!is_eval) attr |= DONT_DELETE; + + // ES#sec-globaldeclarationinstantiation 5.d: + // If hasRestrictedGlobal is true, throw a SyntaxError exception. + Object* result = DeclareGlobal( + isolate, global, name, value, static_cast<PropertyAttributes>(attr), + is_var, is_function, RedeclarationType::kSyntaxError, feedback_vector, + slot); if (isolate->has_pending_exception()) return result; }); return isolate->heap()->undefined_value(); } +} // namespace -RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { +RUNTIME_FUNCTION(Runtime_DeclareGlobals) { HandleScope scope(isolate); - // args[0] == name - // args[1] == language_mode - // args[2] == value (optional) - - // Determine if we need to assign to the variable if it already - // exists (based on the number of arguments). - RUNTIME_ASSERT(args.length() == 3); + DCHECK_EQ(3, args.length()); - CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); + CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); + CONVERT_SMI_ARG_CHECKED(flags, 1); + CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, feedback_vector, 2); - Handle<JSGlobalObject> global(isolate->context()->global_object()); - Handle<Object> result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, Object::SetProperty(global, name, value, language_mode)); - return *result; + return DeclareGlobals(isolate, pairs, flags, feedback_vector); } +// TODO(ishell): merge this with Runtime::kDeclareGlobals once interpreter +// is able to pass feedback vector. +RUNTIME_FUNCTION(Runtime_DeclareGlobalsForInterpreter) { + HandleScope scope(isolate); + DCHECK_EQ(3, args.length()); -RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) { - HandleScope handle_scope(isolate); - // All constants are declared with an initial value. The name - // of the constant is the first argument and the initial value - // is the second. - RUNTIME_ASSERT(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - - Handle<JSGlobalObject> global = isolate->global_object(); - - // Lookup the property as own on the global object. - LookupIterator it(global, name, global, - LookupIterator::HIDDEN_SKIP_INTERCEPTOR); - Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); - DCHECK(maybe.IsJust()); - PropertyAttributes old_attributes = maybe.FromJust(); + CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0); + CONVERT_SMI_ARG_CHECKED(flags, 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 2); - PropertyAttributes attr = - static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); - // Set the value if the property is either missing, or the property attributes - // allow setting the value without invoking an accessor. - if (it.IsFound()) { - // Ignore if we can't reconfigure the value. - if ((old_attributes & DONT_DELETE) != 0) { - if ((old_attributes & READ_ONLY) != 0 || - it.state() == LookupIterator::ACCESSOR) { - return *value; - } - attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY); - } - } + Handle<TypeFeedbackVector> feedback_vector(closure->feedback_vector(), + isolate); + return DeclareGlobals(isolate, pairs, flags, feedback_vector); +} - RETURN_FAILURE_ON_EXCEPTION( - isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr)); +RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) { + HandleScope scope(isolate); + DCHECK_EQ(3, args.length()); + CONVERT_ARG_HANDLE_CHECKED(String, name, 0); + CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); - return *value; + Handle<JSGlobalObject> global(isolate->global_object()); + RETURN_RESULT_OR_FAILURE( + isolate, Object::SetProperty(global, name, value, language_mode)); } - namespace { -Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name, - Handle<Object> initial_value, - PropertyAttributes attr) { - // Declarations are always made in a function, eval or script context, or - // a declaration block scope. - // In the case of eval code, the context passed is the context of the caller, - // which may be some nested context and not the declaration context. +Object* DeclareEvalHelper(Isolate* isolate, Handle<String> name, + Handle<Object> value) { + // Declarations are always made in a function, native, or script context, or + // a declaration block scope. Since this is called from eval, the context + // passed is the context of the caller, which may be some nested context and + // not the declaration context. Handle<Context> context_arg(isolate->context(), isolate); Handle<Context> context(context_arg->declaration_context(), isolate); - // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals. - bool is_var = *initial_value == NULL; - bool is_const = initial_value->IsTheHole(); - bool is_function = initial_value->IsJSFunction(); - DCHECK_EQ(1, - BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function)); + DCHECK(context->IsFunctionContext() || context->IsNativeContext() || + context->IsScriptContext() || + (context->IsBlockContext() && context->has_extension())); + + bool is_function = value->IsJSFunction(); + bool is_var = !is_function; + DCHECK(!is_var || value->IsUndefined(isolate)); int index; PropertyAttributes attributes; - BindingFlags binding_flags; - - if ((attr & EVAL_DECLARED) != 0) { - // Check for a conflict with a lexically scoped variable - context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, - &binding_flags); - if (attributes != ABSENT && - (binding_flags == MUTABLE_CHECK_INITIALIZED || - binding_flags == IMMUTABLE_CHECK_INITIALIZED || - binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY)) { - return ThrowRedeclarationError(isolate, name); - } - attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED); + InitializationFlag init_flag; + VariableMode mode; + + // Check for a conflict with a lexically scoped variable + context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &init_flag, + &mode); + if (attributes != ABSENT && IsLexicalVariableMode(mode)) { + // ES#sec-evaldeclarationinstantiation 5.a.i.1: + // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError + // exception. + // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i: + // Throw a SyntaxError exception. + return ThrowRedeclarationError(isolate, name, + RedeclarationType::kSyntaxError); } Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index, - &attributes, &binding_flags); - if (holder.is_null()) { - // In case of JSProxy, an exception might have been thrown. - if (isolate->has_pending_exception()) return isolate->heap()->exception(); - } + &attributes, &init_flag, &mode); + DCHECK(!isolate->has_pending_exception()); Handle<JSObject> object; - Handle<Object> value = - is_function ? initial_value - : Handle<Object>::cast(isolate->factory()->undefined_value()); - // TODO(verwaest): This case should probably not be covered by this function, - // but by DeclareGlobals instead. if (attributes != ABSENT && holder->IsJSGlobalObject()) { - return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name, - value, attr, is_var, is_const, is_function); + // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b: + // If fnDefinable is false, throw a TypeError exception. + return DeclareGlobal(isolate, Handle<JSGlobalObject>::cast(holder), name, + value, NONE, is_var, is_function, + RedeclarationType::kTypeError); } if (context_arg->extension()->IsJSGlobalObject()) { Handle<JSGlobalObject> global( JSGlobalObject::cast(context_arg->extension()), isolate); - return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, - is_function); + return DeclareGlobal(isolate, global, name, value, NONE, is_var, + is_function, RedeclarationType::kTypeError); } else if (context->IsScriptContext()) { DCHECK(context->global_object()->IsJSGlobalObject()); Handle<JSGlobalObject> global( JSGlobalObject::cast(context->global_object()), isolate); - return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const, - is_function); + return DeclareGlobal(isolate, global, name, value, NONE, is_var, + is_function, RedeclarationType::kTypeError); } if (attributes != ABSENT) { - // The name was declared before; check for conflicting re-declarations. - if (is_const || (attributes & READ_ONLY) != 0) { - return ThrowRedeclarationError(isolate, name); - } + DCHECK_EQ(NONE, attributes); // Skip var re-declarations. if (is_var) return isolate->heap()->undefined_value(); @@ -289,7 +281,7 @@ Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name, DCHECK(is_function); if (index != Context::kNotFound) { DCHECK(holder.is_identical_to(context)); - context->set(index, *initial_value); + context->set(index, *value); return isolate->heap()->undefined_value(); } @@ -318,113 +310,35 @@ Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name, } RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( - object, name, value, attr)); + object, name, value, NONE)); return isolate->heap()->undefined_value(); } } // namespace - -RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) { +RUNTIME_FUNCTION(Runtime_DeclareEvalFunction) { HandleScope scope(isolate); - DCHECK_EQ(3, args.length()); + DCHECK_EQ(2, args.length()); CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1); - CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2); - - PropertyAttributes attributes = - static_cast<PropertyAttributes>(property_attributes->value()); - return DeclareLookupSlot(isolate, name, initial_value, attributes); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); + return DeclareEvalHelper(isolate, name, value); } - -RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) { +RUNTIME_FUNCTION(Runtime_DeclareEvalVar) { HandleScope scope(isolate); - DCHECK(args.length() == 3); - - CONVERT_ARG_HANDLE_CHECKED(Object, value, 0); - DCHECK(!value->IsTheHole()); - // Initializations are always done in a function or native context. - CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1); - Handle<Context> context(context_arg->declaration_context()); - CONVERT_ARG_HANDLE_CHECKED(String, name, 2); - - int index; - PropertyAttributes attributes; - ContextLookupFlags flags = DONT_FOLLOW_CHAINS; - BindingFlags binding_flags; - Handle<Object> holder = - context->Lookup(name, flags, &index, &attributes, &binding_flags); - if (holder.is_null()) { - // In case of JSProxy, an exception might have been thrown. - if (isolate->has_pending_exception()) return isolate->heap()->exception(); - } - - if (index != Context::kNotFound) { - DCHECK(holder->IsContext()); - // Property was found in a context. Perform the assignment if the constant - // was uninitialized. - Handle<Context> context = Handle<Context>::cast(holder); - DCHECK((attributes & READ_ONLY) != 0); - if (context->get(index)->IsTheHole()) context->set(index, *value); - return *value; - } - - PropertyAttributes attr = - static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); - - // Strict mode handling not needed (legacy const is disallowed in strict - // mode). - - // The declared const was configurable, and may have been deleted in the - // meanwhile. If so, re-introduce the variable in the context extension. - if (attributes == ABSENT) { - Handle<Context> declaration_context(context_arg->declaration_context()); - if (declaration_context->IsScriptContext()) { - holder = handle(declaration_context->global_object(), isolate); - } else { - holder = handle(declaration_context->extension_object(), isolate); - DCHECK(!holder.is_null()); - } - CHECK(holder->IsJSObject()); - } else { - // For JSContextExtensionObjects, the initializer can be run multiple times - // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the - // first assignment should go through. For JSGlobalObjects, additionally any - // code can run in between that modifies the declared property. - DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject()); - - LookupIterator it(holder, name, Handle<JSReceiver>::cast(holder), - LookupIterator::HIDDEN_SKIP_INTERCEPTOR); - Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); - if (!maybe.IsJust()) return isolate->heap()->exception(); - PropertyAttributes old_attributes = maybe.FromJust(); - - // Ignore if we can't reconfigure the value. - if ((old_attributes & DONT_DELETE) != 0) { - if ((old_attributes & READ_ONLY) != 0 || - it.state() == LookupIterator::ACCESSOR) { - return *value; - } - attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY); - } - } - - RETURN_FAILURE_ON_EXCEPTION( - isolate, JSObject::SetOwnPropertyIgnoreAttributes( - Handle<JSObject>::cast(holder), name, value, attr)); - - return *value; + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED(String, name, 0); + return DeclareEvalHelper(isolate, name, + isolate->factory()->undefined_value()); } - namespace { // Find the arguments of the JavaScript function invocation that called // into C++ code. Collect these in a newly allocated array of handles. -base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate, - int* total_argc) { +std::unique_ptr<Handle<Object>[]> GetCallerArguments(Isolate* isolate, + int* total_argc) { // Find frame containing arguments passed to the caller. JavaScriptFrameIterator it(isolate); JavaScriptFrame* frame = it.frame(); @@ -449,7 +363,7 @@ base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate, argument_count--; *total_argc = argument_count; - base::SmartArrayPointer<Handle<Object>> param_data( + std::unique_ptr<Handle<Object>[]> param_data( NewArray<Handle<Object>>(*total_argc)); bool should_deoptimize = false; for (int i = 0; i < argument_count; i++) { @@ -470,7 +384,7 @@ base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate, int args_count = frame->ComputeParametersCount(); *total_argc = args_count; - base::SmartArrayPointer<Handle<Object>> param_data( + std::unique_ptr<Handle<Object>[]> param_data( NewArray<Handle<Object>>(*total_argc)); for (int i = 0; i < args_count; i++) { Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); @@ -480,7 +394,6 @@ base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate, } } - template <typename T> Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee, T parameters, int argument_count) { @@ -599,7 +512,7 @@ RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) { // This generic runtime function can also be used when the caller has been // inlined, we use the slow but accurate {GetCallerArguments}. int argument_count = 0; - base::SmartArrayPointer<Handle<Object>> arguments = + std::unique_ptr<Handle<Object>[]> arguments = GetCallerArguments(isolate, &argument_count); HandleArguments argument_getter(arguments.get()); return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); @@ -613,7 +526,7 @@ RUNTIME_FUNCTION(Runtime_NewStrictArguments) { // This generic runtime function can also be used when the caller has been // inlined, we use the slow but accurate {GetCallerArguments}. int argument_count = 0; - base::SmartArrayPointer<Handle<Object>> arguments = + std::unique_ptr<Handle<Object>[]> arguments = GetCallerArguments(isolate, &argument_count); Handle<JSObject> result = isolate->factory()->NewArgumentsObject(callee, argument_count); @@ -639,7 +552,7 @@ RUNTIME_FUNCTION(Runtime_NewRestParameter) { // This generic runtime function can also be used when the caller has been // inlined, we use the slow but accurate {GetCallerArguments}. int argument_count = 0; - base::SmartArrayPointer<Handle<Object>> arguments = + std::unique_ptr<Handle<Object>[]> arguments = GetCallerArguments(isolate, &argument_count); int num_elements = std::max(0, argument_count - start_index); Handle<JSObject> result = @@ -663,12 +576,6 @@ RUNTIME_FUNCTION(Runtime_NewSloppyArguments) { CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); Object** parameters = reinterpret_cast<Object**>(args[1]); CONVERT_SMI_ARG_CHECKED(argument_count, 2); -#ifdef DEBUG - // This runtime function does not materialize the correct arguments when the - // caller has been inlined, better make sure we are not hitting that case. - JavaScriptFrameIterator it(isolate); - DCHECK(!it.frame()->HasInlinedFrames()); -#endif // DEBUG ParameterArguments argument_getter(parameters); return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); } @@ -705,17 +612,27 @@ static Object* FindNameClash(Handle<ScopeInfo> scope_info, ScriptContextTable::LookupResult lookup; if (ScriptContextTable::Lookup(script_context, name, &lookup)) { if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { - return ThrowRedeclarationError(isolate, name); + // ES#sec-globaldeclarationinstantiation 5.b: + // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError + // exception. + return ThrowRedeclarationError(isolate, name, + RedeclarationType::kSyntaxError); } } if (IsLexicalVariableMode(mode)) { LookupIterator it(global_object, name, global_object, - LookupIterator::HIDDEN_SKIP_INTERCEPTOR); + LookupIterator::OWN_SKIP_INTERCEPTOR); Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); if (!maybe.IsJust()) return isolate->heap()->exception(); if ((maybe.FromJust() & DONT_DELETE) != 0) { - return ThrowRedeclarationError(isolate, name); + // ES#sec-globaldeclarationinstantiation 5.a: + // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError + // exception. + // ES#sec-globaldeclarationinstantiation 5.d: + // If hasRestrictedGlobal is true, throw a SyntaxError exception. + return ThrowRedeclarationError(isolate, name, + RedeclarationType::kSyntaxError); } JSGlobalObject::InvalidatePropertyCell(global_object, name); @@ -812,100 +729,6 @@ RUNTIME_FUNCTION(Runtime_PushBlockContext) { } -RUNTIME_FUNCTION(Runtime_IsJSModule) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_CHECKED(Object, obj, 0); - return isolate->heap()->ToBoolean(obj->IsJSModule()); -} - - -RUNTIME_FUNCTION(Runtime_PushModuleContext) { - SealHandleScope shs(isolate); - DCHECK(args.length() == 2); - CONVERT_SMI_ARG_CHECKED(index, 0); - - if (!args[1]->IsScopeInfo()) { - // Module already initialized. Find hosting context and retrieve context. - Context* host = Context::cast(isolate->context())->script_context(); - Context* context = Context::cast(host->get(index)); - DCHECK(context->previous() == isolate->context()); - isolate->set_context(context); - return context; - } - - CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1); - - // Allocate module context. - HandleScope scope(isolate); - Factory* factory = isolate->factory(); - Handle<Context> context = factory->NewModuleContext(scope_info); - Handle<JSModule> module = factory->NewJSModule(context, scope_info); - context->set_module(*module); - Context* previous = isolate->context(); - context->set_previous(previous); - context->set_closure(previous->closure()); - context->set_native_context(previous->native_context()); - isolate->set_context(*context); - - // Find hosting scope and initialize internal variable holding module there. - previous->script_context()->set(index, *context); - - return *context; -} - - -RUNTIME_FUNCTION(Runtime_DeclareModules) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0); - Context* host_context = isolate->context(); - - for (int i = 0; i < descriptions->length(); ++i) { - Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i))); - int host_index = description->host_index(); - Handle<Context> context(Context::cast(host_context->get(host_index))); - Handle<JSModule> module(context->module()); - - for (int j = 0; j < description->length(); ++j) { - Handle<String> name(description->name(j)); - VariableMode mode = description->mode(j); - int index = description->index(j); - switch (mode) { - case VAR: - case LET: - case CONST: - case CONST_LEGACY: - case IMPORT: { - PropertyAttributes attr = - IsImmutableVariableMode(mode) ? FROZEN : SEALED; - Handle<AccessorInfo> info = - Accessors::MakeModuleExport(name, index, attr); - Handle<Object> result = - JSObject::SetAccessor(module, info).ToHandleChecked(); - DCHECK(!result->IsUndefined()); - USE(result); - break; - } - case TEMPORARY: - case DYNAMIC: - case DYNAMIC_GLOBAL: - case DYNAMIC_LOCAL: - UNREACHABLE(); - } - } - - if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR) - .IsNothing()) { - DCHECK(false); - } - } - - DCHECK(!isolate->has_pending_exception()); - return isolate->heap()->undefined_value(); -} - - RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); @@ -913,9 +736,10 @@ RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) { int index; PropertyAttributes attributes; - BindingFlags flags; + InitializationFlag flag; + VariableMode mode; Handle<Object> holder = isolate->context()->Lookup( - name, FOLLOW_CHAINS, &index, &attributes, &flags); + name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode); // If the slot was not found the result is true. if (holder.is_null()) { @@ -948,9 +772,10 @@ MaybeHandle<Object> LoadLookupSlot(Handle<String> name, int index; PropertyAttributes attributes; - BindingFlags flags; + InitializationFlag flag; + VariableMode mode; Handle<Object> holder = isolate->context()->Lookup( - name, FOLLOW_CHAINS, &index, &attributes, &flags); + name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode); if (isolate->has_pending_exception()) return MaybeHandle<Object>(); if (index != Context::kNotFound) { @@ -960,31 +785,14 @@ MaybeHandle<Object> LoadLookupSlot(Handle<String> name, Handle<Object> receiver = isolate->factory()->undefined_value(); Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate); // Check for uninitialized bindings. - switch (flags) { - case MUTABLE_CHECK_INITIALIZED: - case IMMUTABLE_CHECK_INITIALIZED_HARMONY: - if (value->IsTheHole()) { - THROW_NEW_ERROR(isolate, - NewReferenceError(MessageTemplate::kNotDefined, name), - Object); - } - // FALLTHROUGH - case IMMUTABLE_CHECK_INITIALIZED: - if (value->IsTheHole()) { - DCHECK(attributes & READ_ONLY); - value = isolate->factory()->undefined_value(); - } - // FALLTHROUGH - case MUTABLE_IS_INITIALIZED: - case IMMUTABLE_IS_INITIALIZED: - case IMMUTABLE_IS_INITIALIZED_HARMONY: - DCHECK(!value->IsTheHole()); - if (receiver_return) *receiver_return = receiver; - return value; - case MISSING_BINDING: - break; + if (flag == kNeedsInitialization && value->IsTheHole(isolate)) { + THROW_NEW_ERROR(isolate, + NewReferenceError(MessageTemplate::kNotDefined, name), + Object); } - UNREACHABLE(); + DCHECK(!value->IsTheHole(isolate)); + if (receiver_return) *receiver_return = receiver; + return value; } // Otherwise, if the slot was found the holder is a context extension @@ -1024,10 +832,8 @@ RUNTIME_FUNCTION(Runtime_LoadLookupSlot) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - Handle<Object> value; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR)); - return *value; + RETURN_RESULT_OR_FAILURE(isolate, + LoadLookupSlot(name, Object::THROW_ON_ERROR)); } @@ -1035,10 +841,7 @@ RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); CONVERT_ARG_HANDLE_CHECKED(String, name, 0); - Handle<Object> value; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, value, LoadLookupSlot(name, Object::DONT_THROW)); - return *value; + RETURN_RESULT_OR_FAILURE(isolate, LoadLookupSlot(name, Object::DONT_THROW)); } @@ -1065,9 +868,10 @@ MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value, int index; PropertyAttributes attributes; - BindingFlags flags; + InitializationFlag flag; + VariableMode mode; Handle<Object> holder = - context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flags); + context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode); if (holder.is_null()) { // In case of JSProxy, an exception might have been thrown. if (isolate->has_pending_exception()) return MaybeHandle<Object>(); @@ -1075,8 +879,7 @@ MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value, // The property was found in a context slot. if (index != Context::kNotFound) { - if ((flags == MUTABLE_CHECK_INITIALIZED || - flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) && + if (flag == kNeedsInitialization && Handle<Context>::cast(holder)->is_the_hole(index)) { THROW_NEW_ERROR(isolate, NewReferenceError(MessageTemplate::kNotDefined, name), @@ -1123,9 +926,7 @@ RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) { DCHECK_EQ(2, args.length()); CONVERT_ARG_HANDLE_CHECKED(String, name, 0); CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, - StoreLookupSlot(name, value, SLOPPY)); - return *value; + RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, SLOPPY)); } @@ -1134,9 +935,7 @@ RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) { DCHECK_EQ(2, args.length()); CONVERT_ARG_HANDLE_CHECKED(String, name, 0); CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, - StoreLookupSlot(name, value, STRICT)); - return *value; + RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT)); } } // namespace internal |