[js] Remove CORE JS Natives (prologue.js), port extra utils to C++/Torque

- Removes the last `CORE` JS native script: `prologue.js`.
- Removes build step and bootstrapping associated with building/loading `CORE` JS natives.
- Removes `natives_utils_object` from context.
- Deprecates `--expose-natives-as` flag.
- Ports extra utils functions to C++ (`uncurryThis`) or Torque
  (`createPrivateSymbol`, `markPromiseAsHandled`, and `promiseState`).
- Move extra utils constants initialization into bootstrapper
  (`kPROMISE_PENDING`, `kPROMISE_FULFILLED`, `kPROMISE_REJECTED`).
- Removes unused extra utils functions `log` and `logStackTrace`.

Drive-by: Added test coverage for Array#includes being an unscopeable.

Bug: v8:7624
Change-Id: I5d983f8d11b76cb4dd3c2c67592ce1dc88364cd9
Reviewed-on: https://chromium-review.googlesource.com/c/1381672
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Cr-Commit-Position: refs/heads/master@{#58577}
This commit is contained in:
peterwmwong 2019-01-06 23:08:08 -06:00 committed by Commit Bot
parent 2a9a60a5b5
commit 263dce9b57
21 changed files with 263 additions and 399 deletions

View File

@ -711,36 +711,6 @@ template("asm_to_inline_asm") {
}
}
action("js2c") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
script = "tools/js2c.py"
# NOSORT
sources = [
"src/js/macros.py",
"src/message-template.h",
"src/js/prologue.js",
]
outputs = [
"$target_gen_dir/libraries.cc",
]
args = [
rebase_path("$target_gen_dir/libraries.cc", root_build_dir),
"CORE",
] + rebase_path(sources, root_build_dir)
if (v8_use_external_startup_data) {
outputs += [ "$target_gen_dir/libraries.bin" ]
args += [
"--startup_blob",
rebase_path("$target_gen_dir/libraries.bin", root_build_dir),
]
}
}
action("js2c_extras") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
@ -840,14 +810,12 @@ if (v8_use_external_startup_data) {
visibility = [ ":*" ] # Only targets in this file can depend on this.
deps = [
":js2c",
":js2c_experimental_extras",
":js2c_extras",
]
# NOSORT
sources = [
"$target_gen_dir/libraries.bin",
"$target_gen_dir/libraries_extras.bin",
"$target_gen_dir/libraries_experimental_extras.bin",
]
@ -950,6 +918,7 @@ torque_files = [
"src/builtins/array-unshift.tq",
"src/builtins/collections.tq",
"src/builtins/data-view.tq",
"src/builtins/extras-utils.tq",
"src/builtins/object.tq",
"src/builtins/object-fromentries.tq",
"src/builtins/iterator.tq",
@ -967,6 +936,7 @@ torque_namespaces = [
"object",
"typed-array",
"data-view",
"extras-utils",
"test",
]
@ -1252,7 +1222,6 @@ v8_source_set("v8_nosnapshot") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
deps = [
":js2c",
":js2c_experimental_extras",
":js2c_extras",
":v8_base",
@ -1261,7 +1230,6 @@ v8_source_set("v8_nosnapshot") {
sources = [
"$target_gen_dir/experimental-extras-libraries.cc",
"$target_gen_dir/extras-libraries.cc",
"$target_gen_dir/libraries.cc",
"src/snapshot/embedded-empty.cc",
"src/snapshot/snapshot-empty.cc",
]
@ -1271,7 +1239,6 @@ v8_source_set("v8_nosnapshot") {
# TODO(mostynb@vewd.com): don't exclude these http://crbug.com/752428
# Generated source, contains same variable names as libraries.cc
"$target_gen_dir/experimental-extras-libraries.cc",
"$target_gen_dir/libraries.cc",
]
}
@ -1288,7 +1255,6 @@ if (v8_use_snapshot && !v8_use_external_startup_data) {
]
deps = [
":js2c",
":js2c_experimental_extras",
":js2c_extras",
":v8_base",
@ -1305,7 +1271,6 @@ if (v8_use_snapshot && !v8_use_external_startup_data) {
sources = [
"$target_gen_dir/experimental-extras-libraries.cc",
"$target_gen_dir/extras-libraries.cc",
"$target_gen_dir/libraries.cc",
"$target_gen_dir/snapshot.cc",
"src/setup-isolate-deserialize.cc",
]
@ -1324,7 +1289,6 @@ if (v8_use_snapshot && !v8_use_external_startup_data) {
# TODO(mostynb@vewd.com): don't exclude these http://crbug.com/752428
# Generated source, contains same variable names as libraries.cc
"$target_gen_dir/experimental-extras-libraries.cc",
"$target_gen_dir/libraries.cc",
]
}
@ -1337,7 +1301,6 @@ if (v8_use_snapshot && v8_use_external_startup_data) {
visibility = [ ":*" ] # Only targets in this file can depend on this.
deps = [
":js2c",
":js2c_experimental_extras",
":js2c_extras",
":v8_base",
@ -1700,6 +1663,7 @@ v8_source_set("v8_base") {
"src/builtins/builtins-definitions.h",
"src/builtins/builtins-descriptors.h",
"src/builtins/builtins-error.cc",
"src/builtins/builtins-extras-utils.cc",
"src/builtins/builtins-function.cc",
"src/builtins/builtins-global.cc",
"src/builtins/builtins-internal.cc",
@ -4182,7 +4146,6 @@ group("v8_generated_cc_files") {
deps = [
":d8_js2c",
":generate_bytecode_builtins_list",
":js2c",
":js2c_experimental_extras",
":js2c_extras",
":run_torque",

View File

@ -228,6 +228,8 @@ class Genesis {
void InitializeGlobal(Handle<JSGlobalObject> global_object,
Handle<JSFunction> empty_function);
void InitializeExperimentalGlobal();
void InitializeIteratorFunctions();
void InitializeCallSiteBuiltins();
// Depending on the situation, expose and/or get rid of the utils object.
void ConfigureUtilsObject();
@ -303,8 +305,6 @@ class Genesis {
void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);
static bool CallUtilsFunction(Isolate* isolate, const char* name);
static bool CompileExtension(Isolate* isolate, v8::Extension* extension);
Isolate* isolate_;
@ -428,6 +428,15 @@ V8_NOINLINE Handle<JSFunction> CreateFunction(
return result;
}
V8_NOINLINE Handle<JSFunction> CreateFunction(
Isolate* isolate, const char* name, InstanceType type, int instance_size,
int inobject_properties, Handle<Object> prototype,
Builtins::Name builtin_id) {
return CreateFunction(
isolate, isolate->factory()->InternalizeUtf8String(name), type,
instance_size, inobject_properties, prototype, builtin_id);
}
V8_NOINLINE Handle<JSFunction> InstallFunction(
Isolate* isolate, Handle<JSObject> target, Handle<String> name,
InstanceType type, int instance_size, int inobject_properties,
@ -3806,23 +3815,6 @@ void Genesis::InitializeExperimentalGlobal() {
#undef FEATURE_INITIALIZE_GLOBAL
}
bool Bootstrapper::CompileBuiltin(Isolate* isolate, int index) {
Vector<const char> name = Natives::GetScriptName(index);
Handle<String> source_code =
isolate->bootstrapper()->GetNativeSource(CORE, index);
// We pass in extras_utils so that builtin code can set it up for later use
// by actual extras code, compiled with CompileExtraBuiltin.
Handle<Object> global = isolate->global_object();
Handle<Object> utils = isolate->natives_utils_object();
Handle<Object> extras_utils = isolate->extras_utils_object();
Handle<Object> args[] = {global, utils, extras_utils};
return Bootstrapper::CompileNative(isolate, name, source_code,
arraysize(args), args, NATIVES_CODE);
}
bool Bootstrapper::CompileExtraBuiltin(Isolate* isolate, int index) {
HandleScope scope(isolate);
Vector<const char> name = ExtraNatives::GetScriptName(index);
@ -3891,19 +3883,6 @@ bool Bootstrapper::CompileNative(Isolate* isolate, Vector<const char> name,
}
bool Genesis::CallUtilsFunction(Isolate* isolate, const char* name) {
Handle<JSObject> utils =
Handle<JSObject>::cast(isolate->natives_utils_object());
Handle<String> name_string = isolate->factory()->InternalizeUtf8String(name);
Handle<Object> fun = JSObject::GetDataProperty(utils, name_string);
Handle<Object> receiver = isolate->factory()->undefined_value();
Handle<Object> args[] = {utils};
return !Execution::TryCall(isolate, fun, receiver, 1, args,
Execution::MessageHandling::kKeepPending, nullptr)
.is_null();
}
bool Genesis::CompileExtension(Isolate* isolate, v8::Extension* extension) {
Factory* factory = isolate->factory();
HandleScope scope(isolate);
@ -3984,62 +3963,26 @@ static Handle<JSObject> ResolveBuiltinIdHolder(Isolate* isolate,
void Genesis::ConfigureUtilsObject() {
// We still need the utils object after deserialization.
if (isolate()->serializer_enabled()) return;
if (FLAG_expose_natives_as != nullptr &&
strlen(FLAG_expose_natives_as) != 0) {
HandleScope scope(isolate());
Handle<String> natives_key =
factory()->InternalizeUtf8String(FLAG_expose_natives_as);
uint32_t dummy_index;
if (!natives_key->AsArrayIndex(&dummy_index)) {
Handle<Object> utils = isolate()->natives_utils_object();
Handle<JSObject> global = isolate()->global_object();
JSObject::AddProperty(isolate(), global, natives_key, utils, DONT_ENUM);
}
}
// The utils object can be removed for cases that reach this point.
HeapObject undefined = ReadOnlyRoots(heap()).undefined_value();
native_context()->set_natives_utils_object(undefined);
native_context()->set_extras_utils_object(undefined);
}
void Bootstrapper::ExportFromRuntime(Isolate* isolate,
Handle<JSObject> container) {
void Genesis::InitializeIteratorFunctions() {
Isolate* isolate = isolate_;
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<NativeContext> native_context = isolate->native_context();
#define EXPORT_PRIVATE_SYMBOL(_, NAME) \
Handle<String> NAME##_name = factory->InternalizeUtf8String(#NAME); \
JSObject::AddProperty(isolate, container, NAME##_name, factory->NAME(), NONE);
PRIVATE_SYMBOL_LIST_GENERATOR(EXPORT_PRIVATE_SYMBOL, /* not used */)
#undef EXPORT_PRIVATE_SYMBOL
#define EXPORT_PUBLIC_SYMBOL(_, NAME, DESCRIPTION) \
Handle<String> NAME##_name = factory->InternalizeUtf8String(#NAME); \
JSObject::AddProperty(isolate, container, NAME##_name, factory->NAME(), NONE);
PUBLIC_SYMBOL_LIST_GENERATOR(EXPORT_PUBLIC_SYMBOL, /* not used */)
WELL_KNOWN_SYMBOL_LIST_GENERATOR(EXPORT_PUBLIC_SYMBOL, /* not used */)
#undef EXPORT_PUBLIC_SYMBOL
Handle<JSObject> iterator_prototype(
native_context->initial_iterator_prototype(), isolate);
JSObject::AddProperty(isolate, container,
factory->InternalizeUtf8String("IteratorPrototype"),
iterator_prototype, NONE);
{
{ // -- G e n e r a t o r
PrototypeIterator iter(isolate, native_context->generator_function_map());
Handle<JSObject> generator_function_prototype(iter.GetCurrent<JSObject>(),
isolate);
JSObject::AddProperty(
isolate, container,
factory->InternalizeUtf8String("GeneratorFunctionPrototype"),
generator_function_prototype, NONE);
Handle<JSFunction> generator_function_function = InstallFunction(
isolate, container, "GeneratorFunction", JS_FUNCTION_TYPE,
Handle<JSFunction> generator_function_function = CreateFunction(
isolate, "GeneratorFunction", JS_FUNCTION_TYPE,
JSFunction::kSizeWithPrototype, 0, generator_function_prototype,
Builtins::kGeneratorFunctionConstructor);
generator_function_function->set_prototype_or_initial_map(
@ -4061,14 +4004,14 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
*generator_function_function);
}
{
{ // -- A s y n c G e n e r a t o r
PrototypeIterator iter(isolate,
native_context->async_generator_function_map());
Handle<JSObject> async_generator_function_prototype(
iter.GetCurrent<JSObject>(), isolate);
Handle<JSFunction> async_generator_function_function = InstallFunction(
isolate, container, "AsyncGeneratorFunction", JS_FUNCTION_TYPE,
Handle<JSFunction> async_generator_function_function = CreateFunction(
isolate, "AsyncGeneratorFunction", JS_FUNCTION_TYPE,
JSFunction::kSizeWithPrototype, 0, async_generator_function_prototype,
Builtins::kAsyncGeneratorFunctionConstructor);
async_generator_function_function->set_prototype_or_initial_map(
@ -4106,9 +4049,9 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
native_context->set_initial_set_iterator_prototype(*prototype);
// Setup SetIterator constructor.
Handle<JSFunction> set_iterator_function = InstallFunction(
isolate, container, "SetIterator", JS_SET_VALUE_ITERATOR_TYPE,
JSSetIterator::kSize, 0, prototype, Builtins::kIllegal);
Handle<JSFunction> set_iterator_function =
CreateFunction(isolate, "SetIterator", JS_SET_VALUE_ITERATOR_TYPE,
JSSetIterator::kSize, 0, prototype, Builtins::kIllegal);
set_iterator_function->shared()->set_native(false);
Handle<Map> set_value_iterator_map(set_iterator_function->initial_map(),
@ -4137,9 +4080,9 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
native_context->set_initial_map_iterator_prototype(*prototype);
// Setup MapIterator constructor.
Handle<JSFunction> map_iterator_function = InstallFunction(
isolate, container, "MapIterator", JS_MAP_KEY_ITERATOR_TYPE,
JSMapIterator::kSize, 0, prototype, Builtins::kIllegal);
Handle<JSFunction> map_iterator_function =
CreateFunction(isolate, "MapIterator", JS_MAP_KEY_ITERATOR_TYPE,
JSMapIterator::kSize, 0, prototype, Builtins::kIllegal);
map_iterator_function->shared()->set_native(false);
Handle<Map> map_key_iterator_map(map_iterator_function->initial_map(),
@ -4164,8 +4107,8 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
Handle<JSObject> async_function_prototype(iter.GetCurrent<JSObject>(),
isolate);
Handle<JSFunction> async_function_constructor = InstallFunction(
isolate, container, "AsyncFunction", JS_FUNCTION_TYPE,
Handle<JSFunction> async_function_constructor = CreateFunction(
isolate, "AsyncFunction", JS_FUNCTION_TYPE,
JSFunction::kSizeWithPrototype, 0, async_function_prototype,
Builtins::kAsyncFunctionConstructor);
async_function_constructor->set_prototype_or_initial_map(
@ -4208,64 +4151,64 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
native_context->set_async_function_await_resolve_shared_fun(*info);
}
}
{ // -- C a l l S i t e
// Builtin functions for CallSite.
// CallSites are a special case; the constructor is for our private use
// only, therefore we set it up as a builtin that throws. Internally, we use
// CallSiteUtils::Construct to create CallSite objects.
Handle<JSFunction> callsite_fun = InstallFunction(
isolate, container, "CallSite", JS_OBJECT_TYPE, JSObject::kHeaderSize,
0, factory->the_hole_value(), Builtins::kUnsupportedThrower);
callsite_fun->shared()->DontAdaptArguments();
isolate->native_context()->set_callsite_function(*callsite_fun);
{
// Setup CallSite.prototype.
Handle<JSObject> prototype(
JSObject::cast(callsite_fun->instance_prototype()), isolate);
struct FunctionInfo {
const char* name;
Builtins::Name id;
};
FunctionInfo infos[] = {
{"getColumnNumber", Builtins::kCallSitePrototypeGetColumnNumber},
{"getEvalOrigin", Builtins::kCallSitePrototypeGetEvalOrigin},
{"getFileName", Builtins::kCallSitePrototypeGetFileName},
{"getFunction", Builtins::kCallSitePrototypeGetFunction},
{"getFunctionName", Builtins::kCallSitePrototypeGetFunctionName},
{"getLineNumber", Builtins::kCallSitePrototypeGetLineNumber},
{"getMethodName", Builtins::kCallSitePrototypeGetMethodName},
{"getPosition", Builtins::kCallSitePrototypeGetPosition},
{"getPromiseIndex", Builtins::kCallSitePrototypeGetPromiseIndex},
{"getScriptNameOrSourceURL",
Builtins::kCallSitePrototypeGetScriptNameOrSourceURL},
{"getThis", Builtins::kCallSitePrototypeGetThis},
{"getTypeName", Builtins::kCallSitePrototypeGetTypeName},
{"isAsync", Builtins::kCallSitePrototypeIsAsync},
{"isConstructor", Builtins::kCallSitePrototypeIsConstructor},
{"isEval", Builtins::kCallSitePrototypeIsEval},
{"isNative", Builtins::kCallSitePrototypeIsNative},
{"isPromiseAll", Builtins::kCallSitePrototypeIsPromiseAll},
{"isToplevel", Builtins::kCallSitePrototypeIsToplevel},
{"toString", Builtins::kCallSitePrototypeToString}};
PropertyAttributes attrs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
Handle<JSFunction> fun;
for (const FunctionInfo& info : infos) {
SimpleInstallFunction(isolate, prototype, info.name, info.id, 0, true,
attrs);
}
}
}
}
void Genesis::InitializeCallSiteBuiltins() {
Factory* factory = isolate()->factory();
HandleScope scope(isolate());
// -- C a l l S i t e
// Builtin functions for CallSite.
// CallSites are a special case; the constructor is for our private use
// only, therefore we set it up as a builtin that throws. Internally, we use
// CallSiteUtils::Construct to create CallSite objects.
Handle<JSFunction> callsite_fun = CreateFunction(
isolate(), "CallSite", JS_OBJECT_TYPE, JSObject::kHeaderSize, 0,
factory->the_hole_value(), Builtins::kUnsupportedThrower);
callsite_fun->shared()->DontAdaptArguments();
isolate()->native_context()->set_callsite_function(*callsite_fun);
// Setup CallSite.prototype.
Handle<JSObject> prototype(JSObject::cast(callsite_fun->instance_prototype()),
isolate());
struct FunctionInfo {
const char* name;
Builtins::Name id;
};
FunctionInfo infos[] = {
{"getColumnNumber", Builtins::kCallSitePrototypeGetColumnNumber},
{"getEvalOrigin", Builtins::kCallSitePrototypeGetEvalOrigin},
{"getFileName", Builtins::kCallSitePrototypeGetFileName},
{"getFunction", Builtins::kCallSitePrototypeGetFunction},
{"getFunctionName", Builtins::kCallSitePrototypeGetFunctionName},
{"getLineNumber", Builtins::kCallSitePrototypeGetLineNumber},
{"getMethodName", Builtins::kCallSitePrototypeGetMethodName},
{"getPosition", Builtins::kCallSitePrototypeGetPosition},
{"getPromiseIndex", Builtins::kCallSitePrototypeGetPromiseIndex},
{"getScriptNameOrSourceURL",
Builtins::kCallSitePrototypeGetScriptNameOrSourceURL},
{"getThis", Builtins::kCallSitePrototypeGetThis},
{"getTypeName", Builtins::kCallSitePrototypeGetTypeName},
{"isAsync", Builtins::kCallSitePrototypeIsAsync},
{"isConstructor", Builtins::kCallSitePrototypeIsConstructor},
{"isEval", Builtins::kCallSitePrototypeIsEval},
{"isNative", Builtins::kCallSitePrototypeIsNative},
{"isPromiseAll", Builtins::kCallSitePrototypeIsPromiseAll},
{"isToplevel", Builtins::kCallSitePrototypeIsToplevel},
{"toString", Builtins::kCallSitePrototypeToString}};
PropertyAttributes attrs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
Handle<JSFunction> fun;
for (const FunctionInfo& info : infos) {
SimpleInstallFunction(isolate(), prototype, info.name, info.id, 0, true,
attrs);
}
}
#define EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(id) \
void Genesis::InitializeGlobal_##id() {}
@ -4378,9 +4321,9 @@ void Genesis::InitializeGlobal_harmony_string_matchall() {
true);
Handle<JSFunction> regexp_string_iterator_function = CreateFunction(
isolate(), factory()->InternalizeUtf8String("RegExpStringIterator"),
JS_REGEXP_STRING_ITERATOR_TYPE, JSRegExpStringIterator::kSize, 0,
regexp_string_iterator_prototype, Builtins::kIllegal);
isolate(), "RegExpStringIterator", JS_REGEXP_STRING_ITERATOR_TYPE,
JSRegExpStringIterator::kSize, 0, regexp_string_iterator_prototype,
Builtins::kIllegal);
regexp_string_iterator_function->shared()->set_native(false);
native_context()->set_initial_regexp_string_iterator_prototype_map(
regexp_string_iterator_function->initial_map());
@ -4847,12 +4790,6 @@ void Genesis::InstallInternalPackedArray(Handle<JSObject> target,
bool Genesis::InstallNatives() {
HandleScope scope(isolate());
// Set up the utils object as shared container between native scripts.
Handle<JSObject> utils = factory()->NewJSObject(isolate()->object_function());
JSObject::NormalizeProperties(utils, CLEAR_INOBJECT_PROPERTIES, 16,
"utils container for native scripts");
native_context()->set_natives_utils_object(*utils);
// Set up the extras utils object as a shared container between native
// scripts and extras. (Extras consume things added there by native scripts.)
Handle<JSObject> extras_utils =
@ -4861,6 +4798,35 @@ bool Genesis::InstallNatives() {
InstallInternalPackedArray(extras_utils, "InternalPackedArray");
// Extras need the ability to store private state on their objects without
// exposing it to the outside world.
SimpleInstallFunction(isolate_, extras_utils, "createPrivateSymbol",
Builtins::kExtrasUtilsCreatePrivateSymbol, 1, false);
SimpleInstallFunction(isolate_, extras_utils, "uncurryThis",
Builtins::kExtrasUtilsUncurryThis, 1, false);
SimpleInstallFunction(isolate_, extras_utils, "markPromiseAsHandled",
Builtins::kExtrasUtilsMarkPromiseAsHandled, 1, false);
SimpleInstallFunction(isolate_, extras_utils, "promiseState",
Builtins::kExtrasUtilsPromiseState, 1, false);
// [[PromiseState]] values (for extrasUtils.promiseState())
// These values should be kept in sync with PromiseStatus in globals.h
JSObject::AddProperty(
isolate(), extras_utils, "kPROMISE_PENDING",
factory()->NewNumberFromInt(static_cast<int>(Promise::kPending)),
DONT_ENUM);
JSObject::AddProperty(
isolate(), extras_utils, "kPROMISE_FULFILLED",
factory()->NewNumberFromInt(static_cast<int>(Promise::kFulfilled)),
DONT_ENUM);
JSObject::AddProperty(
isolate(), extras_utils, "kPROMISE_REJECTED",
factory()->NewNumberFromInt(static_cast<int>(Promise::kRejected)),
DONT_ENUM);
// v8.createPromise(parent)
Handle<JSFunction> promise_internal_constructor =
SimpleCreateFunction(isolate(), factory()->empty_string(),
@ -4888,10 +4854,8 @@ bool Genesis::InstallNatives() {
JSObject::AddProperty(isolate(), extras_utils, "isPromise",
isolate()->is_promise(), DONT_ENUM);
int builtin_index = 0;
// Only run prologue.js at this point.
DCHECK_EQ(builtin_index, Natives::GetIndex("prologue"));
if (!Bootstrapper::CompileBuiltin(isolate(), builtin_index++)) return false;
JSObject::MigrateSlowToFast(Handle<JSObject>::cast(extras_utils), 0,
"Bootstrapping");
{
// Builtin function for OpaqueReference -- a JSValue-based object,
@ -4905,12 +4869,6 @@ bool Genesis::InstallNatives() {
native_context()->set_opaque_reference_function(*opaque_reference_fun);
}
// Run the rest of the native scripts.
while (builtin_index < Natives::GetBuiltinsCount()) {
if (!Bootstrapper::CompileBuiltin(isolate(), builtin_index++)) return false;
}
if (!CallUtilsFunction(isolate(), "PostNatives")) return false;
auto fast_template_instantiations_cache = isolate()->factory()->NewFixedArray(
TemplateInfo::kFastTemplateInstantiationsCacheSize);
native_context()->set_fast_template_instantiations_cache(
@ -5726,6 +5684,8 @@ Genesis::Genesis(
CreateNewGlobals(global_proxy_template, global_proxy);
InitializeGlobal(global_object, empty_function);
InitializeNormalizedMapCaches();
InitializeIteratorFunctions();
InitializeCallSiteBuiltins();
if (!InstallNatives()) return;
if (!InstallExtraNatives()) return;

View File

@ -91,12 +91,9 @@ class Bootstrapper final {
static bool CompileNative(Isolate* isolate, Vector<const char> name,
Handle<String> source, int argc,
Handle<Object> argv[], NativesFlag natives_flag);
static bool CompileBuiltin(Isolate* isolate, int index);
static bool CompileExtraBuiltin(Isolate* isolate, int index);
static bool CompileExperimentalExtraBuiltin(Isolate* isolate, int index);
static void ExportFromRuntime(Isolate* isolate, Handle<JSObject> container);
private:
// Log newly created Map objects if no snapshot was used.
void LogAllMaps();

View File

@ -602,6 +602,10 @@ namespace internal {
CPP(MakeTypeError) \
CPP(MakeURIError) \
\
/* ExtrasUtils */ \
CPP(ExtrasUtilsUncurryThis) \
CPP(ExtrasUtilsCallReflectApply) \
\
/* Function */ \
CPP(FunctionConstructor) \
ASM(FunctionPrototypeApply, Dummy) \

View File

@ -0,0 +1,93 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
#include "src/elements.h"
#include "src/counters.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
namespace {
enum UncurryThisFunctionContextSlot {
kFunctionSlot = Context::MIN_CONTEXT_SLOTS,
kFunctionContextLength,
};
} // namespace
// These functions are key for safe meta-programming:
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
//
// Technically they could all be derived from combinations of
// Function.prototype.{bind,call,apply} but that introduces lots of layers of
// indirection.
//
// Equivalent to:
//
// function uncurryThis(func) {
// return function(thisArg, ...args) {
// return %reflect_apply(func, thisArg, args);
// };
// };
//
BUILTIN(ExtrasUtilsUncurryThis) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
Handle<JSFunction> function = args.at<JSFunction>(1);
Handle<NativeContext> native_context(isolate->context()->native_context(),
isolate);
Handle<Context> context = isolate->factory()->NewBuiltinContext(
native_context,
static_cast<int>(UncurryThisFunctionContextSlot::kFunctionContextLength));
context->set(static_cast<int>(UncurryThisFunctionContextSlot::kFunctionSlot),
*function);
Handle<SharedFunctionInfo> info =
isolate->factory()->NewSharedFunctionInfoForBuiltin(
isolate->factory()->empty_string(),
Builtins::kExtrasUtilsCallReflectApply, kNormalFunction);
info->DontAdaptArguments();
Handle<Map> map = isolate->strict_function_without_prototype_map();
Handle<JSFunction> new_bound_function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(map, info, context);
return *new_bound_function;
}
BUILTIN(ExtrasUtilsCallReflectApply) {
HandleScope scope(isolate);
Handle<Context> context(isolate->context(), isolate);
Handle<NativeContext> native_context(isolate->context()->native_context(),
isolate);
Handle<JSFunction> function(
JSFunction::cast(context->get(
static_cast<int>(UncurryThisFunctionContextSlot::kFunctionSlot))),
isolate);
Handle<Object> this_arg = args.at(1);
int const rest_args_atart = 2;
Arguments argv(args.length() - rest_args_atart,
args.address_of_arg_at(rest_args_atart));
Handle<JSArray> rest_args_array = isolate->factory()->NewJSArray(0);
RETURN_FAILURE_ON_EXCEPTION(
isolate, ArrayConstructInitializeElements(rest_args_array, &argv));
Handle<Object> reflect_apply_args[] = {function, this_arg, rest_args_array};
Handle<JSFunction> reflect_apply(native_context->reflect_apply(), isolate);
RETURN_RESULT_OR_FAILURE(
isolate,
Execution::Call(isolate, reflect_apply,
isolate->factory()->undefined_value(),
arraysize(reflect_apply_args), reflect_apply_args));
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,24 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace extras_utils {
extern runtime CreatePrivateSymbol(Context, Object): HeapObject;
extern runtime PromiseMarkAsHandled(Context, Object): Undefined;
extern runtime PromiseStatus(Context, Object): Smi;
javascript builtin ExtrasUtilsCreatePrivateSymbol(
context: Context, receiver: Object, ...arguments): HeapObject {
return CreatePrivateSymbol(context, arguments[0]);
}
javascript builtin ExtrasUtilsMarkPromiseAsHandled(
context: Context, receiver: Object, ...arguments): Undefined {
return PromiseMarkAsHandled(context, arguments[0]);
}
javascript builtin ExtrasUtilsPromiseState(
context: Context, receiver: Object, ...arguments): Smi {
return PromiseStatus(context, arguments[0]);
}
}

View File

@ -205,7 +205,6 @@ enum ContextLookupFlags {
V(MATH_RANDOM_STATE_INDEX, ByteArray, math_random_state) \
V(MATH_RANDOM_CACHE_INDEX, FixedDoubleArray, math_random_cache) \
V(MESSAGE_LISTENERS_INDEX, TemplateList, message_listeners) \
V(NATIVES_UTILS_OBJECT_INDEX, Object, natives_utils_object) \
V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache) \
V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \

View File

@ -873,7 +873,6 @@ DEFINE_BOOL(disable_old_api_accessors, false,
"prototype chain")
// bootstrapper.cc
DEFINE_STRING(expose_natives_as, nullptr, "expose natives in global object")
DEFINE_BOOL(expose_free_buffer, false, "expose freeBuffer extension")
DEFINE_BOOL(expose_gc, false, "expose gc extension")
DEFINE_STRING(expose_gc_as, nullptr,

View File

@ -1,111 +0,0 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function(global, utils, extrasUtils) {
"use strict";
%CheckIsBootstrapping();
// -----------------------------------------------------------------------
// Utils
var imports = UNDEFINED;
var exports_container = %ExportFromRuntime({});
// Export to other scripts.
function Export(f) {
f(exports_container);
}
// Import from other scripts. The actual importing happens in PostNatives so
// that we can import from scripts executed later. However, that means that
// the import is not available until the very end.
function Import(f) {
f.next = imports;
imports = f;
}
// -----------------------------------------------------------------------
// To be called by bootstrapper
function PostNatives(utils) {
%CheckIsBootstrapping();
for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
imports(exports_container);
}
exports_container = UNDEFINED;
utils.Export = UNDEFINED;
utils.Import = UNDEFINED;
utils.PostNatives = UNDEFINED;
}
// -----------------------------------------------------------------------
%OptimizeObjectForAddingMultipleProperties(utils, 14);
utils.Import = Import;
utils.Export = Export;
utils.PostNatives = PostNatives;
%ToFastProperties(utils);
// -----------------------------------------------------------------------
%OptimizeObjectForAddingMultipleProperties(extrasUtils, 11);
extrasUtils.logStackTrace = function logStackTrace() {
%DebugTrace();
};
extrasUtils.log = function log() {
let message = '';
for (const arg of arguments) {
message += arg;
}
%GlobalPrint(message);
};
// Extras need the ability to store private state on their objects without
// exposing it to the outside world.
extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) {
return %CreatePrivateSymbol(name);
};
// These functions are key for safe meta-programming:
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
//
// Technically they could all be derived from combinations of
// Function.prototype.{bind,call,apply} but that introduces lots of layers of
// indirection.
extrasUtils.uncurryThis = function uncurryThis(func) {
return function(thisArg, ...args) {
return %reflect_apply(func, thisArg, args);
};
};
extrasUtils.markPromiseAsHandled = function markPromiseAsHandled(promise) {
%PromiseMarkAsHandled(promise);
};
extrasUtils.promiseState = function promiseState(promise) {
return %PromiseStatus(promise);
};
// [[PromiseState]] values (for extrasUtils.promiseState())
// These values should be kept in sync with PromiseStatus in globals.h
extrasUtils.kPROMISE_PENDING = 0;
extrasUtils.kPROMISE_FULFILLED = 1;
extrasUtils.kPROMISE_REJECTED = 2;
%ToFastProperties(extrasUtils);
})

View File

@ -32,18 +32,6 @@ RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_ExportFromRuntime) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0);
CHECK(isolate->bootstrapper()->IsActive());
JSObject::NormalizeProperties(container, KEEP_INOBJECT_PROPERTIES, 10,
"ExportFromRuntime");
Bootstrapper::ExportFromRuntime(isolate, container);
JSObject::MigrateSlowToFast(container, 0, "ExportFromRuntime");
return *container;
}
RUNTIME_FUNCTION(Runtime_Throw) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());

View File

@ -216,7 +216,6 @@ namespace internal {
I(CreateAsyncFromSyncIterator, 1, 1) \
F(CreateListFromArrayLike, 1, 1) \
F(CreateTemplateObject, 1, 1) \
F(ExportFromRuntime, 1, 1) \
F(GetAndResetRuntimeCallStats, -1 /* <= 2 */, 1) \
F(IncrementUseCounter, 1, 1) \
F(Interrupt, 0, 1) \

View File

@ -17,10 +17,6 @@ NativesExternalStringResource::NativesExternalStringResource(NativeType type,
Vector<const char> source;
DCHECK_LE(0, index);
switch (type_) {
case CORE:
DCHECK(index < Natives::GetBuiltinsCount());
source = Natives::GetScriptSource(index);
break;
case EXTRAS:
DCHECK(index < ExtraNatives::GetBuiltinsCount());
source = ExtraNatives::GetScriptSource(index);

View File

@ -133,9 +133,8 @@ static StartupData* natives_blob_ = nullptr;
* Read the Natives blob, as previously set by SetNativesFromFile.
*/
void ReadNatives() {
if (natives_blob_ && NativesHolder<CORE>::empty()) {
if (natives_blob_ && NativesHolder<EXTRAS>::empty()) {
SnapshotByteSource bytes(natives_blob_->data, natives_blob_->raw_size);
NativesHolder<CORE>::set(NativesStore::MakeFromScriptsSource(&bytes));
NativesHolder<EXTRAS>::set(NativesStore::MakeFromScriptsSource(&bytes));
NativesHolder<EXPERIMENTAL_EXTRAS>::set(
NativesStore::MakeFromScriptsSource(&bytes));
@ -163,7 +162,6 @@ void SetNativesFromFile(StartupData* natives_blob) {
* Release memory allocated by SetNativesFromFile.
*/
void DisposeNatives() {
NativesHolder<CORE>::Dispose();
NativesHolder<EXTRAS>::Dispose();
NativesHolder<EXPERIMENTAL_EXTRAS>::Dispose();
}
@ -208,7 +206,6 @@ Vector<const char> NativesCollection<type>::GetScriptsSource() {
template Vector<const char> NativesCollection<T>::GetScriptSource(int i); \
template Vector<const char> NativesCollection<T>::GetScriptName(int i); \
template Vector<const char> NativesCollection<T>::GetScriptsSource();
INSTANTIATE_TEMPLATES(CORE)
INSTANTIATE_TEMPLATES(EXTRAS)
INSTANTIATE_TEMPLATES(EXPERIMENTAL_EXTRAS)
#undef INSTANTIATE_TEMPLATES

View File

@ -15,7 +15,6 @@ namespace v8 {
namespace internal {
enum NativeType {
CORE,
EXTRAS,
EXPERIMENTAL_EXTRAS,
D8,
@ -42,7 +41,6 @@ class V8_EXPORT_PRIVATE NativesCollection {
static Vector<const char> GetScriptsSource();
};
typedef NativesCollection<CORE> Natives;
typedef NativesCollection<EXTRAS> ExtraNatives;
typedef NativesCollection<EXPERIMENTAL_EXTRAS> ExperimentalExtraNatives;
@ -63,8 +61,8 @@ class NativesExternalStringResource final
size_t length() const override { return length_; }
v8::String::ExternalOneByteStringResource* EncodeForSerialization() const {
DCHECK(type_ == CORE || type_ == EXTRAS);
intptr_t val = (index_ << 1) | ((type_ == CORE) ? 0 : 1);
DCHECK(type_ == EXTRAS);
intptr_t val = (index_ << 1) | 1;
val = val << kPointerSizeLog2; // Pointer align.
return reinterpret_cast<v8::String::ExternalOneByteStringResource*>(val);
}
@ -73,9 +71,9 @@ class NativesExternalStringResource final
static NativesExternalStringResource* DecodeForDeserialization(
const v8::String::ExternalOneByteStringResource* encoded) {
intptr_t val = reinterpret_cast<intptr_t>(encoded) >> kPointerSizeLog2;
NativeType type = (val & 1) ? EXTRAS : CORE;
DCHECK(val & 1);
int index = static_cast<int>(val >> 1);
return new NativesExternalStringResource(type, index);
return new NativesExternalStringResource(EXTRAS, index);
}
private:

View File

@ -4980,49 +4980,6 @@ TEST(PreprocessStackTrace) {
}
static bool utils_has_been_collected = false;
static void UtilsHasBeenCollected(
const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
utils_has_been_collected = true;
data.GetParameter()->Reset();
}
TEST(BootstrappingExports) {
// Expose utils object and delete it to observe that it is indeed
// being garbage-collected.
FLAG_expose_natives_as = "utils";
CcTest::InitializeVM();
v8::Isolate* isolate = CcTest::isolate();
LocalContext env;
if (Snapshot::HasContextSnapshot(CcTest::i_isolate(), 0)) return;
utils_has_been_collected = false;
v8::Persistent<v8::Object> utils;
{
v8::HandleScope scope(isolate);
v8::Local<v8::String> name = v8_str("utils");
utils.Reset(isolate, CcTest::global()
->Get(env.local(), name)
.ToLocalChecked()
->ToObject(env.local())
.ToLocalChecked());
CHECK(CcTest::global()->Delete(env.local(), name).FromJust());
}
utils.SetWeak(&utils, UtilsHasBeenCollected,
v8::WeakCallbackType::kParameter);
CcTest::CollectAllAvailableGarbage();
CHECK(utils_has_been_collected);
}
void AllocateInSpace(Isolate* isolate, size_t bytes, AllocationSpace space) {
CHECK_LE(FixedArray::kHeaderSize, bytes);
CHECK(IsAligned(bytes, kTaggedSize));

View File

@ -26750,6 +26750,11 @@ TEST(ExtrasUtilsObject) {
.ToLocalChecked()
.As<v8::Boolean>();
CHECK_EQ(false, thenable_is_promise->Value());
auto uncurry_this = result->Get(env.local(), v8_str("uncurryThis"))
.ToLocalChecked()
.As<v8::Boolean>();
CHECK_EQ(true, uncurry_this->Value());
}

View File

@ -4269,7 +4269,6 @@ i::MaybeHandle<i::Script> FindScript(
UNINITIALIZED_TEST(LoadedAtStartupScripts) {
i::FLAG_expose_gc = true;
i::FLAG_expose_natives_as = "natives";
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
@ -4296,17 +4295,12 @@ UNINITIALIZED_TEST(LoadedAtStartupScripts) {
scripts.emplace_back(script, i_isolate);
}
}
CHECK_EQ(count_by_type[i::Script::TYPE_NATIVE],
i::Natives::GetBuiltinsCount());
CHECK_EQ(count_by_type[i::Script::TYPE_NATIVE], 0);
CHECK_EQ(count_by_type[i::Script::TYPE_EXTENSION], 2);
CHECK_EQ(count_by_type[i::Script::TYPE_NORMAL], 1);
CHECK_EQ(count_by_type[i::Script::TYPE_WASM], 0);
CHECK_EQ(count_by_type[i::Script::TYPE_INSPECTOR], 0);
i::Handle<i::Script> native_prologue_script =
FindScript(i_isolate, scripts, "native prologue.js").ToHandleChecked();
CHECK_EQ(native_prologue_script->type(), i::Script::TYPE_NATIVE);
i::Handle<i::Script> gc_script =
FindScript(i_isolate, scripts, "v8/gc").ToHandleChecked();
CHECK_EQ(gc_script->type(), i::Script::TYPE_EXTENSION);

View File

@ -103,6 +103,10 @@
promiseStateToString(fulfilledPromise) + ' ' +
promiseStateToString(rejectedPromise);
const uncurryThis = v8.uncurryThis(function (a, b, c, d, e) {
return (this + a + b + c + d + e) === 21;
})(1, 2, 3, 4, 5, 6);
return {
privateSymbol: v8.createPrivateSymbol('sym'),
fulfilledPromise, // should be fulfilled with 1
@ -111,7 +115,8 @@
rejectedButHandledPromise, // should be rejected but have a handler
promiseStates, // should be the string "pending fulfilled rejected"
promiseIsPromise: v8.isPromise(fulfilledPromise), // should be true
thenableIsPromise: v8.isPromise({ then() { } }) // should be false
thenableIsPromise: v8.isPromise({ then() { } }), // should be false
uncurryThis // should be true
};
};
})

View File

@ -188,7 +188,7 @@ TEST(FlagsRemoveIncomplete) {
// if the list of arguments ends unexpectedly.
SetFlagsToDefault();
int argc = 3;
const char* argv[] = {"", "--testing-bool-flag", "--expose-natives-as"};
const char* argv[] = {"", "--testing-bool-flag", "--expose-gc-as"};
CHECK_EQ(2, FlagList::SetFlagsFromCommandLine(&argc,
const_cast<char **>(argv),
true));

View File

@ -99,6 +99,7 @@ function TestArrayPrototypeUnscopables() {
var flat = 'local flat';
var flatMap = 'local flatMap';
var keys = 'local keys';
var includes = 'local includes';
var values = 'local values';
var array = [];
@ -112,6 +113,7 @@ function TestArrayPrototypeUnscopables() {
assertEquals('local findIndex', findIndex);
assertEquals('local flat', flat);
assertEquals('local flatMap', flatMap);
assertEquals('local includes', includes);
assertEquals('local keys', keys);
assertEquals('local values', values);
assertEquals(42, toString);

View File

@ -1,5 +0,0 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-natives-as 1