Commit 36190b91 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

Reland 2 ScriptContext CLs

Changing script context handling from bytecode based to metadata on the
function. This fixes the debugger to explicitly check the code rather
than implicitly relying on a NewScriptContext bytecode causing side
effects.

Bug: chromium:1043151
Tbr: ulan@chromium.org
Change-Id: I38c5c04d7c76155e0a055ae6efd57f25986bdb7d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2013117Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65920}
parent 6f3cf7aa
...@@ -96,11 +96,9 @@ Object MakeGenericError(Isolate* isolate, BuiltinArguments args, ...@@ -96,11 +96,9 @@ Object MakeGenericError(Isolate* isolate, BuiltinArguments args,
DCHECK(template_index->IsSmi()); DCHECK(template_index->IsSmi());
RETURN_RESULT_OR_FAILURE( return *ErrorUtils::MakeGenericError(
isolate, ErrorUtils::MakeGenericError( isolate, constructor, MessageTemplateFromInt(Smi::ToInt(*template_index)),
isolate, constructor, arg0, arg1, arg2, SKIP_NONE);
MessageTemplateFromInt(Smi::ToInt(*template_index)), arg0,
arg1, arg2, SKIP_NONE));
} }
} // namespace } // namespace
...@@ -130,10 +128,9 @@ BUILTIN(MakeURIError) { ...@@ -130,10 +128,9 @@ BUILTIN(MakeURIError) {
Handle<JSFunction> constructor = isolate->uri_error_function(); Handle<JSFunction> constructor = isolate->uri_error_function();
Handle<Object> undefined = isolate->factory()->undefined_value(); Handle<Object> undefined = isolate->factory()->undefined_value();
MessageTemplate template_index = MessageTemplate::kURIMalformed; MessageTemplate template_index = MessageTemplate::kURIMalformed;
RETURN_RESULT_OR_FAILURE( return *ErrorUtils::MakeGenericError(isolate, constructor, template_index,
isolate, undefined, undefined, undefined,
ErrorUtils::MakeGenericError(isolate, constructor, template_index, SKIP_NONE);
undefined, undefined, undefined, SKIP_NONE));
} }
} // namespace internal } // namespace internal
......
...@@ -864,6 +864,8 @@ DebugInfo::SideEffectState DebugEvaluate::FunctionGetSideEffectState( ...@@ -864,6 +864,8 @@ DebugInfo::SideEffectState DebugEvaluate::FunctionGetSideEffectState(
info->DebugName().ToCString().get()); info->DebugName().ToCString().get());
} }
if (info->needs_script_context()) return DebugInfo::kHasSideEffects;
DCHECK(info->is_compiled()); DCHECK(info->is_compiled());
if (info->HasBytecodeArray()) { if (info->HasBytecodeArray()) {
// Check bytecodes against whitelist. // Check bytecodes against whitelist.
......
...@@ -157,6 +157,84 @@ Handle<Code> JSEntry(Isolate* isolate, Execution::Target execution_target, ...@@ -157,6 +157,84 @@ Handle<Code> JSEntry(Isolate* isolate, Execution::Target execution_target,
UNREACHABLE(); UNREACHABLE();
} }
MaybeHandle<Context> NewScriptContext(Isolate* isolate,
Handle<JSFunction> function) {
SaveAndSwitchContext save(isolate, function->context());
SharedFunctionInfo sfi = function->shared();
Handle<Script> script(Script::cast(sfi.script()), isolate);
Handle<ScopeInfo> scope_info(sfi.scope_info(), isolate);
Handle<NativeContext> native_context(NativeContext::cast(function->context()),
isolate);
Handle<JSGlobalObject> global_object(native_context->global_object(),
isolate);
Handle<ScriptContextTable> script_context(
native_context->script_context_table(), isolate);
// Find name clashes.
for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
Handle<String> name(scope_info->ContextLocalName(var), isolate);
VariableMode mode = scope_info->ContextLocalMode(var);
ScriptContextTable::LookupResult lookup;
if (ScriptContextTable::Lookup(isolate, *script_context, *name, &lookup)) {
if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
Handle<Context> context = ScriptContextTable::GetContext(
isolate, script_context, lookup.context_index);
// If we are trying to re-declare a REPL-mode let as a let, allow it.
if (!(mode == VariableMode::kLet && lookup.mode == VariableMode::kLet &&
scope_info->IsReplModeScope() &&
context->scope_info().IsReplModeScope())) {
// ES#sec-globaldeclarationinstantiation 5.b:
// If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
// exception.
MessageLocation location(script, 0, 1);
isolate->ThrowAt(isolate->factory()->NewSyntaxError(
MessageTemplate::kVarRedeclaration, name),
&location);
return MaybeHandle<Context>();
}
}
}
if (IsLexicalVariableMode(mode)) {
LookupIterator it(isolate, global_object, name, global_object,
LookupIterator::OWN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
// Can't fail since the we looking up own properties on the global object
// skipping interceptors.
CHECK(!maybe.IsNothing());
if ((maybe.FromJust() & DONT_DELETE) != 0) {
// 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.
MessageLocation location(script, 0, 1);
isolate->ThrowAt(isolate->factory()->NewSyntaxError(
MessageTemplate::kVarRedeclaration, name),
&location);
return MaybeHandle<Context>();
}
JSGlobalObject::InvalidatePropertyCell(global_object, name);
}
}
Handle<Context> result =
isolate->factory()->NewScriptContext(native_context, scope_info);
int header = scope_info->ContextHeaderLength();
for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
if (scope_info->ContextLocalInitFlag(var) == kNeedsInitialization) {
result->set(header + var, ReadOnlyRoots(isolate).the_hole_value());
}
}
Handle<ScriptContextTable> new_script_context_table =
ScriptContextTable::Extend(script_context, result);
native_context->set_script_context_table(*new_script_context_table);
return result;
}
V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate,
const InvokeParams& params) { const InvokeParams& params) {
RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kInvoke); RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kInvoke);
...@@ -206,6 +284,22 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, ...@@ -206,6 +284,22 @@ V8_WARN_UNUSED_RESULT MaybeHandle<Object> Invoke(Isolate* isolate,
} }
return value; return value;
} }
// Set up a ScriptContext when running scripts that need it.
if (function->shared().needs_script_context()) {
Handle<Context> context;
if (!NewScriptContext(isolate, function).ToHandle(&context)) {
if (params.message_handling == Execution::MessageHandling::kReport) {
isolate->ReportPendingMessages();
}
return MaybeHandle<Object>();
}
// We mutate the context if we allocate a script context. This is
// guaranteed to only happen once in a native context since scripts will
// always produce name clashes with themselves.
function->set_context(*context);
}
} }
// Entering JavaScript. // Entering JavaScript.
......
...@@ -1342,6 +1342,30 @@ Object Isolate::StackOverflow() { ...@@ -1342,6 +1342,30 @@ Object Isolate::StackOverflow() {
return ReadOnlyRoots(heap()).exception(); return ReadOnlyRoots(heap()).exception();
} }
void Isolate::ThrowAt(Handle<JSObject> exception, MessageLocation* location) {
Handle<Name> key_start_pos = factory()->error_start_pos_symbol();
Object::SetProperty(this, exception, key_start_pos,
handle(Smi::FromInt(location->start_pos()), this),
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
Handle<Name> key_end_pos = factory()->error_end_pos_symbol();
Object::SetProperty(this, exception, key_end_pos,
handle(Smi::FromInt(location->end_pos()), this),
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
Handle<Name> key_script = factory()->error_script_symbol();
Object::SetProperty(this, exception, key_script, location->script(),
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
Throw(*exception, location);
}
Object Isolate::TerminateExecution() { Object Isolate::TerminateExecution() {
return Throw(ReadOnlyRoots(this).termination_exception(), nullptr); return Throw(ReadOnlyRoots(this).termination_exception(), nullptr);
} }
......
...@@ -772,6 +772,8 @@ class Isolate final : private HiddenFactory { ...@@ -772,6 +772,8 @@ class Isolate final : private HiddenFactory {
return MaybeHandle<T>(); return MaybeHandle<T>();
} }
void ThrowAt(Handle<JSObject> exception, MessageLocation* location);
void set_console_delegate(debug::ConsoleDelegate* delegate) { void set_console_delegate(debug::ConsoleDelegate* delegate) {
console_delegate_ = delegate; console_delegate_ = delegate;
} }
......
...@@ -990,7 +990,7 @@ MaybeHandle<String> MessageFormatter::Format(Isolate* isolate, ...@@ -990,7 +990,7 @@ MaybeHandle<String> MessageFormatter::Format(Isolate* isolate,
return builder.Finish(); return builder.Finish();
} }
MaybeHandle<Object> ErrorUtils::Construct( MaybeHandle<JSObject> ErrorUtils::Construct(
Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target, Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
Handle<Object> message, FrameSkipMode mode, Handle<Object> caller, Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
StackTraceCollection stack_trace_collection) { StackTraceCollection stack_trace_collection) {
...@@ -1007,7 +1007,7 @@ MaybeHandle<Object> ErrorUtils::Construct( ...@@ -1007,7 +1007,7 @@ MaybeHandle<Object> ErrorUtils::Construct(
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate, err, isolate, err,
JSObject::New(target, new_target_recv, Handle<AllocationSite>::null()), JSObject::New(target, new_target_recv, Handle<AllocationSite>::null()),
Object); JSObject);
// 3. If message is not undefined, then // 3. If message is not undefined, then
// a. Let msg be ? ToString(message). // a. Let msg be ? ToString(message).
...@@ -1019,23 +1019,23 @@ MaybeHandle<Object> ErrorUtils::Construct( ...@@ -1019,23 +1019,23 @@ MaybeHandle<Object> ErrorUtils::Construct(
if (!message->IsUndefined(isolate)) { if (!message->IsUndefined(isolate)) {
Handle<String> msg_string; Handle<String> msg_string;
ASSIGN_RETURN_ON_EXCEPTION(isolate, msg_string, ASSIGN_RETURN_ON_EXCEPTION(isolate, msg_string,
Object::ToString(isolate, message), Object); Object::ToString(isolate, message), JSObject);
RETURN_ON_EXCEPTION( RETURN_ON_EXCEPTION(
isolate, isolate,
JSObject::SetOwnPropertyIgnoreAttributes( JSObject::SetOwnPropertyIgnoreAttributes(
err, isolate->factory()->message_string(), msg_string, DONT_ENUM), err, isolate->factory()->message_string(), msg_string, DONT_ENUM),
Object); JSObject);
} }
switch (stack_trace_collection) { switch (stack_trace_collection) {
case StackTraceCollection::kDetailed: case StackTraceCollection::kDetailed:
RETURN_ON_EXCEPTION( RETURN_ON_EXCEPTION(
isolate, isolate->CaptureAndSetDetailedStackTrace(err), Object); isolate, isolate->CaptureAndSetDetailedStackTrace(err), JSObject);
V8_FALLTHROUGH; V8_FALLTHROUGH;
case StackTraceCollection::kSimple: case StackTraceCollection::kSimple:
RETURN_ON_EXCEPTION( RETURN_ON_EXCEPTION(
isolate, isolate->CaptureAndSetSimpleStackTrace(err, mode, caller), isolate, isolate->CaptureAndSetSimpleStackTrace(err, mode, caller),
Object); JSObject);
break; break;
case StackTraceCollection::kNone: case StackTraceCollection::kNone:
break; break;
...@@ -1144,7 +1144,7 @@ Handle<String> DoFormatMessage(Isolate* isolate, MessageTemplate index, ...@@ -1144,7 +1144,7 @@ Handle<String> DoFormatMessage(Isolate* isolate, MessageTemplate index,
} // namespace } // namespace
// static // static
MaybeHandle<Object> ErrorUtils::MakeGenericError( Handle<JSObject> ErrorUtils::MakeGenericError(
Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index, Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2, Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
FrameSkipMode mode) { FrameSkipMode mode) {
...@@ -1167,8 +1167,11 @@ MaybeHandle<Object> ErrorUtils::MakeGenericError( ...@@ -1167,8 +1167,11 @@ MaybeHandle<Object> ErrorUtils::MakeGenericError(
DCHECK(mode != SKIP_UNTIL_SEEN); DCHECK(mode != SKIP_UNTIL_SEEN);
Handle<Object> no_caller; Handle<Object> no_caller;
// The call below can't fail because constructor is a builtin.
DCHECK(constructor->shared().HasBuiltinId());
return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode, return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode,
no_caller, StackTraceCollection::kDetailed); no_caller, StackTraceCollection::kDetailed)
.ToHandleChecked();
} }
namespace { namespace {
......
...@@ -269,14 +269,14 @@ class ErrorUtils : public AllStatic { ...@@ -269,14 +269,14 @@ class ErrorUtils : public AllStatic {
// |kNone| is useful when you don't need the stack information at all, for // |kNone| is useful when you don't need the stack information at all, for
// example when creating a deserialized error. // example when creating a deserialized error.
enum class StackTraceCollection { kDetailed, kSimple, kNone }; enum class StackTraceCollection { kDetailed, kSimple, kNone };
static MaybeHandle<Object> Construct( static MaybeHandle<JSObject> Construct(
Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target, Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
Handle<Object> message, FrameSkipMode mode, Handle<Object> caller, Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
StackTraceCollection stack_trace_collection); StackTraceCollection stack_trace_collection);
static MaybeHandle<String> ToString(Isolate* isolate, Handle<Object> recv); static MaybeHandle<String> ToString(Isolate* isolate, Handle<Object> recv);
static MaybeHandle<Object> MakeGenericError( static Handle<JSObject> MakeGenericError(
Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index, Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2, Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
FrameSkipMode mode); FrameSkipMode mode);
......
...@@ -1267,9 +1267,10 @@ Handle<Context> Factory::NewScriptContext(Handle<NativeContext> outer, ...@@ -1267,9 +1267,10 @@ Handle<Context> Factory::NewScriptContext(Handle<NativeContext> outer,
Handle<ScopeInfo> scope_info) { Handle<ScopeInfo> scope_info) {
DCHECK_EQ(scope_info->scope_type(), SCRIPT_SCOPE); DCHECK_EQ(scope_info->scope_type(), SCRIPT_SCOPE);
int variadic_part_length = scope_info->ContextLength(); int variadic_part_length = scope_info->ContextLength();
Handle<Context> context = NewContext( Handle<Context> context =
isolate()->script_context_map(), Context::SizeFor(variadic_part_length), NewContext(handle(outer->script_context_map(), isolate()),
variadic_part_length, AllocationType::kOld); Context::SizeFor(variadic_part_length), variadic_part_length,
AllocationType::kOld);
context->set_scope_info(*scope_info); context->set_scope_info(*scope_info);
context->set_previous(*outer); context->set_previous(*outer);
DCHECK(context->IsScriptContext()); DCHECK(context->IsScriptContext());
...@@ -2084,51 +2085,30 @@ Handle<FreshlyAllocatedBigInt> Factory::NewBigInt(int length, ...@@ -2084,51 +2085,30 @@ Handle<FreshlyAllocatedBigInt> Factory::NewBigInt(int length,
return handle(bigint, isolate()); return handle(bigint, isolate());
} }
Handle<Object> Factory::NewError(Handle<JSFunction> constructor, Handle<JSObject> Factory::NewError(Handle<JSFunction> constructor,
MessageTemplate template_index, MessageTemplate template_index,
Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg0, Handle<Object> arg1,
Handle<Object> arg2) { Handle<Object> arg2) {
HandleScope scope(isolate()); HandleScope scope(isolate());
if (isolate()->bootstrapper()->IsActive()) {
// During bootstrapping we cannot construct error objects.
return scope.CloseAndEscape(NewStringFromAsciiChecked(
MessageFormatter::TemplateString(template_index)));
}
if (arg0.is_null()) arg0 = undefined_value(); if (arg0.is_null()) arg0 = undefined_value();
if (arg1.is_null()) arg1 = undefined_value(); if (arg1.is_null()) arg1 = undefined_value();
if (arg2.is_null()) arg2 = undefined_value(); if (arg2.is_null()) arg2 = undefined_value();
Handle<Object> result; return scope.CloseAndEscape(ErrorUtils::MakeGenericError(
if (!ErrorUtils::MakeGenericError(isolate(), constructor, template_index, isolate(), constructor, template_index, arg0, arg1, arg2, SKIP_NONE));
arg0, arg1, arg2, SKIP_NONE)
.ToHandle(&result)) {
// If an exception is thrown while
// running the factory method, use the exception as the result.
DCHECK(isolate()->has_pending_exception());
result = handle(isolate()->pending_exception(), isolate());
isolate()->clear_pending_exception();
}
return scope.CloseAndEscape(result);
} }
Handle<Object> Factory::NewError(Handle<JSFunction> constructor, Handle<JSObject> Factory::NewError(Handle<JSFunction> constructor,
Handle<String> message) { Handle<String> message) {
// Construct a new error object. If an exception is thrown, use the exception // Construct a new error object. If an exception is thrown, use the exception
// as the result. // as the result.
Handle<Object> no_caller; Handle<Object> no_caller;
MaybeHandle<Object> maybe_error = ErrorUtils::Construct( return ErrorUtils::Construct(isolate(), constructor, constructor, message,
isolate(), constructor, constructor, message, SKIP_NONE, no_caller, SKIP_NONE, no_caller,
ErrorUtils::StackTraceCollection::kDetailed); ErrorUtils::StackTraceCollection::kDetailed)
if (maybe_error.is_null()) { .ToHandleChecked();
DCHECK(isolate()->has_pending_exception());
maybe_error = handle(isolate()->pending_exception(), isolate());
isolate()->clear_pending_exception();
}
return maybe_error.ToHandleChecked();
} }
Handle<Object> Factory::NewInvalidStringLengthError() { Handle<Object> Factory::NewInvalidStringLengthError() {
...@@ -2143,9 +2123,9 @@ Handle<Object> Factory::NewInvalidStringLengthError() { ...@@ -2143,9 +2123,9 @@ Handle<Object> Factory::NewInvalidStringLengthError() {
} }
#define DEFINE_ERROR(NAME, name) \ #define DEFINE_ERROR(NAME, name) \
Handle<Object> Factory::New##NAME(MessageTemplate template_index, \ Handle<JSObject> Factory::New##NAME( \
Handle<Object> arg0, Handle<Object> arg1, \ MessageTemplate template_index, Handle<Object> arg0, \
Handle<Object> arg2) { \ Handle<Object> arg1, Handle<Object> arg2) { \
return NewError(isolate()->name##_function(), template_index, arg0, arg1, \ return NewError(isolate()->name##_function(), template_index, arg0, arg1, \
arg2); \ arg2); \
} }
......
...@@ -770,21 +770,21 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> { ...@@ -770,21 +770,21 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
Handle<BytecodeArray> CopyBytecodeArray(Handle<BytecodeArray>); Handle<BytecodeArray> CopyBytecodeArray(Handle<BytecodeArray>);
// Interface for creating error objects. // Interface for creating error objects.
Handle<Object> NewError(Handle<JSFunction> constructor, Handle<JSObject> NewError(Handle<JSFunction> constructor,
Handle<String> message); Handle<String> message);
Handle<Object> NewInvalidStringLengthError(); Handle<Object> NewInvalidStringLengthError();
inline Handle<Object> NewURIError(); inline Handle<Object> NewURIError();
Handle<Object> NewError(Handle<JSFunction> constructor, Handle<JSObject> NewError(Handle<JSFunction> constructor,
MessageTemplate template_index, MessageTemplate template_index,
Handle<Object> arg0 = Handle<Object>(), Handle<Object> arg0 = Handle<Object>(),
Handle<Object> arg1 = Handle<Object>(), Handle<Object> arg1 = Handle<Object>(),
Handle<Object> arg2 = Handle<Object>()); Handle<Object> arg2 = Handle<Object>());
#define DECLARE_ERROR(NAME) \ #define DECLARE_ERROR(NAME) \
Handle<Object> New##NAME(MessageTemplate template_index, \ Handle<JSObject> New##NAME(MessageTemplate template_index, \
Handle<Object> arg0 = Handle<Object>(), \ Handle<Object> arg0 = Handle<Object>(), \
Handle<Object> arg1 = Handle<Object>(), \ Handle<Object> arg1 = Handle<Object>(), \
Handle<Object> arg2 = Handle<Object>()); Handle<Object> arg2 = Handle<Object>());
......
...@@ -1166,7 +1166,7 @@ void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) { ...@@ -1166,7 +1166,7 @@ void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) {
BuildGeneratorPrologue(); BuildGeneratorPrologue();
} }
if (closure_scope()->NeedsContext()) { if (closure_scope()->NeedsContext() && !closure_scope()->is_script_scope()) {
// Push a new inner context scope for the function. // Push a new inner context scope for the function.
BuildNewLocalActivationContext(); BuildNewLocalActivationContext();
ContextScope local_function_context(this, closure_scope()); ContextScope local_function_context(this, closure_scope());
...@@ -1320,8 +1320,7 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { ...@@ -1320,8 +1320,7 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
switch (variable->location()) { switch (variable->location()) {
case VariableLocation::UNALLOCATED: case VariableLocation::UNALLOCATED:
globals_builder()->record_global_declaration(); UNREACHABLE();
break;
case VariableLocation::LOCAL: case VariableLocation::LOCAL:
if (variable->binding_needs_init()) { if (variable->binding_needs_init()) {
Register destination(builder()->Local(variable->index())); Register destination(builder()->Local(variable->index()));
...@@ -1376,9 +1375,7 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { ...@@ -1376,9 +1375,7 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
switch (variable->location()) { switch (variable->location()) {
case VariableLocation::UNALLOCATED: case VariableLocation::UNALLOCATED:
AddToEagerLiteralsIfEager(decl->fun()); UNREACHABLE();
globals_builder()->record_global_declaration();
break;
case VariableLocation::PARAMETER: case VariableLocation::PARAMETER:
case VariableLocation::LOCAL: { case VariableLocation::LOCAL: {
VisitFunctionLiteral(decl->fun()); VisitFunctionLiteral(decl->fun());
...@@ -1435,9 +1432,26 @@ void BytecodeGenerator::VisitModuleNamespaceImports() { ...@@ -1435,9 +1432,26 @@ void BytecodeGenerator::VisitModuleNamespaceImports() {
void BytecodeGenerator::VisitGlobalDeclarations(Declaration::List* decls) { void BytecodeGenerator::VisitGlobalDeclarations(Declaration::List* decls) {
RegisterAllocationScope register_scope(this); RegisterAllocationScope register_scope(this);
VisitDeclarations(decls); bool has_global_declaration = false;
for (Declaration* decl : *decls) {
Variable* var = decl->var();
DCHECK(var->is_used());
if (var->location() == VariableLocation::UNALLOCATED) {
// var or function.
has_global_declaration = true;
if (decl->IsFunctionDeclaration()) {
FunctionDeclaration* f = static_cast<FunctionDeclaration*>(decl);
AddToEagerLiteralsIfEager(f->fun());
}
} else {
// let or const. Handled in NewScriptContext.
DCHECK(decl->IsVariableDeclaration());
DCHECK(IsLexicalVariableMode(var->mode()));
}
}
if (!globals_builder()->has_global_declaration()) return; if (!has_global_declaration) return;
globals_builder()->record_global_declaration();
DCHECK(!globals_builder()->processed()); DCHECK(!globals_builder()->processed());
globals_builder()->set_constant_pool_entry( globals_builder()->set_constant_pool_entry(
...@@ -5982,13 +5996,7 @@ void BytecodeGenerator::BuildNewLocalActivationContext() { ...@@ -5982,13 +5996,7 @@ void BytecodeGenerator::BuildNewLocalActivationContext() {
DCHECK_EQ(current_scope(), closure_scope()); DCHECK_EQ(current_scope(), closure_scope());
// Create the appropriate context. // Create the appropriate context.
if (scope->is_script_scope()) { if (scope->is_module_scope()) {
Register scope_reg = register_allocator()->NewRegister();
builder()
->LoadLiteral(scope)
.StoreAccumulatorInRegister(scope_reg)
.CallRuntime(Runtime::kNewScriptContext, scope_reg);
} else if (scope->is_module_scope()) {
// We don't need to do anything for the outer script scope. // We don't need to do anything for the outer script scope.
DCHECK(scope->outer_scope()->is_script_scope()); DCHECK(scope->outer_scope()->is_script_scope());
......
...@@ -581,6 +581,10 @@ ScopeType ScopeInfo::scope_type() const { ...@@ -581,6 +581,10 @@ ScopeType ScopeInfo::scope_type() const {
return ScopeTypeBits::decode(Flags()); return ScopeTypeBits::decode(Flags());
} }
bool ScopeInfo::is_script_scope() const {
return length() > 0 && scope_type() == SCRIPT_SCOPE;
}
bool ScopeInfo::SloppyEvalCanExtendVars() const { bool ScopeInfo::SloppyEvalCanExtendVars() const {
bool sloppy_eval_can_extend_vars = bool sloppy_eval_can_extend_vars =
length() > 0 && SloppyEvalCanExtendVarsBit::decode(Flags()); length() > 0 && SloppyEvalCanExtendVarsBit::decode(Flags());
......
...@@ -196,6 +196,8 @@ class ScopeInfo : public FixedArray, public TorqueGeneratedScopeFlagsFields { ...@@ -196,6 +196,8 @@ class ScopeInfo : public FixedArray, public TorqueGeneratedScopeFlagsFields {
// Return the outer ScopeInfo if present. // Return the outer ScopeInfo if present.
ScopeInfo OuterScopeInfo() const; ScopeInfo OuterScopeInfo() const;
bool is_script_scope() const;
// Returns true if this ScopeInfo has a black list attached containing // Returns true if this ScopeInfo has a black list attached containing
// stack allocated local variables. // stack allocated local variables.
V8_EXPORT_PRIVATE bool HasLocalsBlackList() const; V8_EXPORT_PRIVATE bool HasLocalsBlackList() const;
......
...@@ -148,6 +148,16 @@ void SharedFunctionInfo::SetName(String name) { ...@@ -148,6 +148,16 @@ void SharedFunctionInfo::SetName(String name) {
UpdateFunctionMapIndex(); UpdateFunctionMapIndex();
} }
bool SharedFunctionInfo::is_script() const {
return scope_info().is_script_scope() &&
Script::cast(script()).compilation_type() ==
Script::COMPILATION_TYPE_HOST;
}
bool SharedFunctionInfo::needs_script_context() const {
return is_script() && scope_info().ContextLocalCount() > 0;
}
AbstractCode SharedFunctionInfo::abstract_code() { AbstractCode SharedFunctionInfo::abstract_code() {
if (HasBytecodeArray()) { if (HasBytecodeArray()) {
return AbstractCode::cast(GetBytecodeArray()); return AbstractCode::cast(GetBytecodeArray());
......
...@@ -223,6 +223,9 @@ class SharedFunctionInfo : public HeapObject, ...@@ -223,6 +223,9 @@ class SharedFunctionInfo : public HeapObject,
inline void set_raw_scope_info(ScopeInfo scope_info, inline void set_raw_scope_info(ScopeInfo scope_info,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER); WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline bool is_script() const;
inline bool needs_script_context() const;
// End position of this function in the script source. // End position of this function in the script source.
V8_EXPORT_PRIVATE int EndPosition() const; V8_EXPORT_PRIVATE int EndPosition() const;
......
...@@ -97,37 +97,9 @@ void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate, ...@@ -97,37 +97,9 @@ void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate,
isolate->debug()->OnCompileError(script); isolate->debug()->OnCompileError(script);
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
Handle<Object> error = Handle<JSObject> error =
factory->NewSyntaxError(error_details_.message(), argument); factory->NewSyntaxError(error_details_.message(), argument);
isolate->ThrowAt(error, &location);
if (!error->IsJSObject()) {
isolate->Throw(*error, &location);
return;
}
Handle<JSObject> jserror = Handle<JSObject>::cast(error);
Handle<Name> key_start_pos = factory->error_start_pos_symbol();
Object::SetProperty(isolate, jserror, key_start_pos,
handle(Smi::FromInt(location.start_pos()), isolate),
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
Handle<Name> key_end_pos = factory->error_end_pos_symbol();
Object::SetProperty(isolate, jserror, key_end_pos,
handle(Smi::FromInt(location.end_pos()), isolate),
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
Handle<Name> key_script = factory->error_script_symbol();
Object::SetProperty(isolate, jserror, key_script, script,
StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Check();
isolate->Throw(*error, &location);
} }
Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest( Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
......
...@@ -597,76 +597,6 @@ RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) { ...@@ -597,76 +597,6 @@ RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
return *function; return *function;
} }
static Object FindNameClash(Isolate* isolate, Handle<ScopeInfo> scope_info,
Handle<JSGlobalObject> global_object,
Handle<ScriptContextTable> script_context) {
for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
Handle<String> name(scope_info->ContextLocalName(var), isolate);
VariableMode mode = scope_info->ContextLocalMode(var);
ScriptContextTable::LookupResult lookup;
if (ScriptContextTable::Lookup(isolate, *script_context, *name, &lookup)) {
if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
Handle<Context> context = ScriptContextTable::GetContext(
isolate, script_context, lookup.context_index);
// If we are trying to re-declare a REPL-mode let as a let, allow it.
if (!(mode == VariableMode::kLet && lookup.mode == VariableMode::kLet &&
scope_info->IsReplModeScope() &&
context->scope_info().IsReplModeScope())) {
// 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(isolate, global_object, name, global_object,
LookupIterator::OWN_SKIP_INTERCEPTOR);
Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
if (maybe.IsNothing()) return ReadOnlyRoots(isolate).exception();
if ((maybe.FromJust() & DONT_DELETE) != 0) {
// 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);
}
}
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_NewScriptContext) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
Handle<NativeContext> native_context(NativeContext::cast(isolate->context()),
isolate);
Handle<JSGlobalObject> global_object(native_context->global_object(),
isolate);
Handle<ScriptContextTable> script_context_table(
native_context->script_context_table(), isolate);
Object name_clash_result =
FindNameClash(isolate, scope_info, global_object, script_context_table);
if (isolate->has_pending_exception()) return name_clash_result;
Handle<Context> result =
isolate->factory()->NewScriptContext(native_context, scope_info);
Handle<ScriptContextTable> new_script_context_table =
ScriptContextTable::Extend(script_context_table, result);
native_context->set_script_context_table(*new_script_context_table);
return *result;
}
RUNTIME_FUNCTION(Runtime_NewFunctionContext) { RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
......
...@@ -396,7 +396,6 @@ namespace internal { ...@@ -396,7 +396,6 @@ namespace internal {
F(NewClosure_Tenured, 2, 1) \ F(NewClosure_Tenured, 2, 1) \
F(NewFunctionContext, 1, 1) \ F(NewFunctionContext, 1, 1) \
F(NewRestParameter, 1, 1) \ F(NewRestParameter, 1, 1) \
F(NewScriptContext, 1, 1) \
F(NewSloppyArguments, 3, 1) \ F(NewSloppyArguments, 3, 1) \
F(NewSloppyArguments_Generic, 1, 1) \ F(NewSloppyArguments_Generic, 1, 1) \
F(NewStrictArguments, 1, 1) \ F(NewStrictArguments, 1, 1) \
......
...@@ -15,7 +15,7 @@ Evaluating 'let a = 239;' ...@@ -15,7 +15,7 @@ Evaluating 'let a = 239;'
columnNumber : 0 columnNumber : 0
exception : { exception : {
className : SyntaxError className : SyntaxError
description : SyntaxError: Identifier 'a' has already been declared at <anonymous>:1:1 description : SyntaxError: Identifier 'a' has already been declared
objectId : <objectId> objectId : <objectId>
subtype : error subtype : error
type : object type : object
...@@ -27,7 +27,7 @@ Evaluating 'let a = 239;' ...@@ -27,7 +27,7 @@ Evaluating 'let a = 239;'
} }
result : { result : {
className : SyntaxError className : SyntaxError
description : SyntaxError: Identifier 'a' has already been declared at <anonymous>:1:1 description : SyntaxError: Identifier 'a' has already been declared
objectId : <objectId> objectId : <objectId>
subtype : error subtype : error
type : object type : object
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment