Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Unified Diff: src/bootstrapper.cc

Issue 1138173002: Reland "Use function wrapper argument to expose internal arrays to native scripts." (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressed nit Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/array.js ('k') | src/contexts.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/bootstrapper.cc
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index f3dd682871b74964a4afd0860aed1381c49c1944..f0278ca666724daf7faf1f0a10384e2a1e4f9d1e 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -217,7 +217,7 @@ class Genesis BASE_EMBEDDED {
HARMONY_SHIPPING(DECLARE_FEATURE_INITIALIZATION)
#undef DECLARE_FEATURE_INITIALIZATION
- Handle<JSFunction> InstallInternalArray(Handle<JSBuiltinsObject> builtins,
+ Handle<JSFunction> InstallInternalArray(Handle<JSObject> target,
const char* name,
ElementsKind elements_kind);
bool InstallNatives();
@@ -307,19 +307,15 @@ class Genesis BASE_EMBEDDED {
FunctionMode function_mode);
void SetStrongFunctionInstanceDescriptor(Handle<Map> map);
- static bool CompileBuiltin(Isolate* isolate, int index);
+ static bool CompileBuiltin(Isolate* isolate, int index,
+ Handle<JSObject> shared);
static bool CompileExperimentalBuiltin(Isolate* isolate, int index);
static bool CompileExtraBuiltin(Isolate* isolate, int index);
- static bool CompileNative(Isolate* isolate,
- Vector<const char> name,
- Handle<String> source);
- static bool CompileScriptCached(Isolate* isolate,
- Vector<const char> name,
- Handle<String> source,
- SourceCodeCache* cache,
- v8::Extension* extension,
- Handle<Context> top_context,
- bool use_runtime_context);
+ static bool CompileNative(Isolate* isolate, Vector<const char> name,
+ Handle<String> source, int argc,
+ Handle<Object> argv[]);
+
+ static bool CompileExtension(Isolate* isolate, v8::Extension* extension);
Isolate* isolate_;
Handle<Context> result_;
@@ -1441,34 +1437,45 @@ void Genesis::InitializeExperimentalGlobal() {
}
-bool Genesis::CompileBuiltin(Isolate* isolate, int index) {
+bool Genesis::CompileBuiltin(Isolate* isolate, int index,
+ Handle<JSObject> shared) {
Vector<const char> name = Natives::GetScriptName(index);
Handle<String> source_code =
isolate->bootstrapper()->SourceLookup<Natives>(index);
- return CompileNative(isolate, name, source_code);
+ Handle<Object> global = isolate->global_object();
+ Handle<Object> exports = isolate->builtin_exports_object();
+ Handle<Object> args[] = {global, shared, exports};
+ return CompileNative(isolate, name, source_code, arraysize(args), args);
}
bool Genesis::CompileExperimentalBuiltin(Isolate* isolate, int index) {
+ HandleScope scope(isolate);
Vector<const char> name = ExperimentalNatives::GetScriptName(index);
Handle<String> source_code =
isolate->bootstrapper()->SourceLookup<ExperimentalNatives>(index);
- return CompileNative(isolate, name, source_code);
+ Handle<Object> global = isolate->global_object();
+ Handle<Object> exports = isolate->builtin_exports_object();
+ Handle<Object> args[] = {global, exports};
+ return CompileNative(isolate, name, source_code, arraysize(args), args);
}
bool Genesis::CompileExtraBuiltin(Isolate* isolate, int index) {
+ HandleScope scope(isolate);
Vector<const char> name = ExtraNatives::GetScriptName(index);
Handle<String> source_code =
isolate->bootstrapper()->SourceLookup<ExtraNatives>(index);
- return CompileNative(isolate, name, source_code);
+ Handle<Object> global = isolate->global_object();
+ Handle<Object> exports = isolate->builtin_exports_object();
+ Handle<Object> args[] = {global, exports};
+ return CompileNative(isolate, name, source_code, arraysize(args), args);
}
-bool Genesis::CompileNative(Isolate* isolate,
- Vector<const char> name,
- Handle<String> source) {
- HandleScope scope(isolate);
+bool Genesis::CompileNative(Isolate* isolate, Vector<const char> name,
+ Handle<String> source, int argc,
+ Handle<Object> argv[]) {
SuppressDebug compiling_natives(isolate->debug());
// During genesis, the boilerplate for stack overflow won't work until the
// environment has been at least partially initialized. Add a stack check
@@ -1476,78 +1483,72 @@ bool Genesis::CompileNative(Isolate* isolate,
StackLimitCheck check(isolate);
if (check.HasOverflowed()) return false;
- bool result = CompileScriptCached(isolate,
- name,
- source,
- NULL,
- NULL,
- Handle<Context>(isolate->context()),
- true);
- DCHECK(isolate->has_pending_exception() != result);
- if (!result) isolate->clear_pending_exception();
- return result;
+ Handle<Context> context(isolate->context());
+
+ Handle<String> script_name =
+ isolate->factory()->NewStringFromUtf8(name).ToHandleChecked();
+ Handle<SharedFunctionInfo> function_info = Compiler::CompileScript(
+ source, script_name, 0, 0, false, false, Handle<Object>(), context, NULL,
+ NULL, ScriptCompiler::kNoCompileOptions, NATIVES_CODE, false);
+
+ DCHECK(context->IsNativeContext());
+
+ Handle<Context> runtime_context(context->runtime_context());
+ Handle<JSBuiltinsObject> receiver(context->builtins());
+ Handle<JSFunction> fun =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(function_info,
+ runtime_context);
+
+ // For non-extension scripts, run script to get the function wrapper.
+ Handle<Object> wrapper;
+ if (!Execution::Call(isolate, fun, receiver, 0, NULL).ToHandle(&wrapper)) {
+ return false;
+ }
+ // Then run the function wrapper.
+ return !Execution::Call(isolate, Handle<JSFunction>::cast(wrapper), receiver,
+ argc, argv).is_null();
}
-bool Genesis::CompileScriptCached(Isolate* isolate,
- Vector<const char> name,
- Handle<String> source,
- SourceCodeCache* cache,
- v8::Extension* extension,
- Handle<Context> top_context,
- bool use_runtime_context) {
+bool Genesis::CompileExtension(Isolate* isolate, v8::Extension* extension) {
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SharedFunctionInfo> function_info;
+ Handle<String> source =
+ isolate->factory()
+ ->NewExternalStringFromOneByte(extension->source())
+ .ToHandleChecked();
+ DCHECK(source->IsOneByteRepresentation());
+
// If we can't find the function in the cache, we compile a new
// function and insert it into the cache.
- if (cache == NULL || !cache->Lookup(name, &function_info)) {
- DCHECK(source->IsOneByteRepresentation());
+ Vector<const char> name = CStrVector(extension->name());
+ SourceCodeCache* cache = isolate->bootstrapper()->extensions_cache();
+ Handle<Context> context(isolate->context());
+ DCHECK(context->IsNativeContext());
+
+ if (!cache->Lookup(name, &function_info)) {
Handle<String> script_name =
factory->NewStringFromUtf8(name).ToHandleChecked();
function_info = Compiler::CompileScript(
- source, script_name, 0, 0, false, false, Handle<Object>(), top_context,
- extension, NULL, ScriptCompiler::kNoCompileOptions,
- use_runtime_context ? NATIVES_CODE : NOT_NATIVES_CODE, false);
+ source, script_name, 0, 0, false, false, Handle<Object>(), context,
+ extension, NULL, ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE,
+ false);
if (function_info.is_null()) return false;
- if (cache != NULL) cache->Add(name, function_info);
+ cache->Add(name, function_info);
}
// Set up the function context. Conceptually, we should clone the
// function before overwriting the context but since we're in a
// single-threaded environment it is not strictly necessary.
- DCHECK(top_context->IsNativeContext());
- Handle<Context> context =
- Handle<Context>(use_runtime_context
- ? Handle<Context>(top_context->runtime_context())
- : top_context);
Handle<JSFunction> fun =
factory->NewFunctionFromSharedFunctionInfo(function_info, context);
// Call function using either the runtime object or the global
// object as the receiver. Provide no parameters.
- Handle<Object> receiver =
- Handle<Object>(use_runtime_context
- ? top_context->builtins()
- : top_context->global_object(),
- isolate);
- MaybeHandle<Object> result;
- if (extension == NULL) {
- // For non-extension scripts, run script to get the function wrapper.
- Handle<Object> wrapper;
- if (!Execution::Call(isolate, fun, receiver, 0, NULL).ToHandle(&wrapper)) {
- return false;
- }
- // Then run the function wrapper.
- Handle<Object> global_obj(top_context->global_object(), isolate);
- Handle<Object> args[] = {global_obj};
- result = Execution::Call(isolate, Handle<JSFunction>::cast(wrapper),
- receiver, arraysize(args), args);
- } else {
- result = Execution::Call(isolate, fun, receiver, 0, NULL);
- }
- return !result.is_null();
+ Handle<Object> receiver = isolate->global_object();
+ return !Execution::Call(isolate, fun, receiver, 0, NULL).is_null();
}
@@ -1818,10 +1819,9 @@ void Genesis::InitializeGlobal_harmony_tostring() {
}
-Handle<JSFunction> Genesis::InstallInternalArray(
- Handle<JSBuiltinsObject> builtins,
- const char* name,
- ElementsKind elements_kind) {
+Handle<JSFunction> Genesis::InstallInternalArray(Handle<JSObject> target,
+ const char* name,
+ ElementsKind elements_kind) {
// --- I n t e r n a l A r r a y ---
// An array constructor on the builtins object that works like
// the public Array constructor, except that its prototype
@@ -1830,9 +1830,9 @@ Handle<JSFunction> Genesis::InstallInternalArray(
// must not be leaked to user code.
Handle<JSObject> prototype =
factory()->NewJSObject(isolate()->object_function(), TENURED);
- Handle<JSFunction> array_function = InstallFunction(
- builtins, name, JS_ARRAY_TYPE, JSArray::kSize,
- prototype, Builtins::kInternalArrayCode);
+ Handle<JSFunction> array_function =
+ InstallFunction(target, name, JS_ARRAY_TYPE, JSArray::kSize, prototype,
+ Builtins::kInternalArrayCode);
InternalArrayConstructorStub internal_array_constructor_stub(isolate());
Handle<Code> code = internal_array_constructor_stub.GetCode();
@@ -1910,6 +1910,19 @@ bool Genesis::InstallNatives() {
native_context()->set_runtime_context(*context);
+ // Set up shared object to set up cross references between native scripts.
+ // "shared" is used for cross references between native scripts that are part
+ // of the snapshot. "builtin_exports" is used for experimental natives.
+ Handle<JSObject> shared =
+ factory()->NewJSObject(isolate()->object_function());
+ JSObject::NormalizeProperties(shared, CLEAR_INOBJECT_PROPERTIES, 16,
+ "container to share between native scripts");
+ Handle<JSObject> builtin_exports =
+ factory()->NewJSObject(isolate()->object_function());
+ JSObject::NormalizeProperties(builtin_exports, CLEAR_INOBJECT_PROPERTIES, 16,
+ "container to export to experimental natives");
+ native_context()->set_builtin_exports_object(*builtin_exports);
+
{ // -- S c r i p t
// Builtin functions for Script.
Handle<JSFunction> script_fun = InstallFunction(
@@ -2082,13 +2095,13 @@ bool Genesis::InstallNatives() {
// through a common bottleneck that would make the SMI_ONLY -> FAST_ELEMENT
// transition easy to trap. Moreover, they rarely are smi-only.
{
- Handle<JSFunction> array_function =
- InstallInternalArray(builtins, "InternalArray", FAST_HOLEY_ELEMENTS);
+ HandleScope scope(isolate());
+ Handle<JSObject> builtin_exports =
+ Handle<JSObject>::cast(isolate()->builtin_exports_object());
+ Handle<JSFunction> array_function = InstallInternalArray(
+ builtin_exports, "InternalArray", FAST_HOLEY_ELEMENTS);
native_context()->set_internal_array_function(*array_function);
- }
-
- {
- InstallInternalArray(builtins, "InternalPackedArray", FAST_ELEMENTS);
+ InstallInternalArray(builtin_exports, "InternalPackedArray", FAST_ELEMENTS);
}
{ // -- S e t I t e r a t o r
@@ -2181,13 +2194,15 @@ bool Genesis::InstallNatives() {
#undef INSTALL_PUBLIC_SYMBOL
}
- // Install natives.
+ // Install natives. Everything exported to experimental natives is also
+ // shared to regular natives.
+ TransferNamedProperties(builtin_exports, shared);
int i = Natives::GetDebuggerCount();
- if (!CompileBuiltin(isolate(), i)) return false;
+ if (!CompileBuiltin(isolate(), i, shared)) return false;
if (!InstallJSBuiltins(builtins)) return false;
for (++i; i < Natives::GetBuiltinsCount(); ++i) {
- if (!CompileBuiltin(isolate(), i)) return false;
+ if (!CompileBuiltin(isolate(), i, shared)) return false;
}
InstallNativeFunctions();
@@ -2502,14 +2517,21 @@ bool Genesis::InstallSpecialObjects(Handle<Context> native_context) {
Handle<Smi> stack_trace_limit(Smi::FromInt(FLAG_stack_trace_limit), isolate);
JSObject::AddProperty(Error, name, stack_trace_limit, NONE);
+ Handle<Object> builtin_exports(native_context->builtin_exports_object(),
+ isolate);
+ native_context->set_builtin_exports_object(Smi::FromInt(0));
+
// Expose the natives in global if a name for it is specified.
if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
- Handle<String> natives =
+ Handle<String> natives_key =
factory->InternalizeUtf8String(FLAG_expose_natives_as);
uint32_t dummy_index;
- if (natives->AsArrayIndex(&dummy_index)) return true;
- JSObject::AddProperty(global, natives, handle(global->builtins()),
- DONT_ENUM);
+ if (natives_key->AsArrayIndex(&dummy_index)) return true;
+ Handle<JSBuiltinsObject> natives(global->builtins());
+ JSObject::AddProperty(global, natives_key, natives, DONT_ENUM);
+ Handle<String> builtin_exports_key =
+ factory->NewStringFromAsciiChecked("builtin_exports");
+ JSObject::AddProperty(natives, builtin_exports_key, builtin_exports, NONE);
}
// Expose the stack trace symbol to native JS.
@@ -2653,17 +2675,7 @@ bool Genesis::InstallExtension(Isolate* isolate,
}
}
// We do not expect this to throw an exception. Change this if it does.
- Handle<String> source_code =
- isolate->factory()
- ->NewExternalStringFromOneByte(extension->source())
- .ToHandleChecked();
- bool result = CompileScriptCached(isolate,
- CStrVector(extension->name()),
- source_code,
- isolate->bootstrapper()->extensions_cache(),
- extension,
- Handle<Context>(isolate->context()),
- false);
+ bool result = CompileExtension(isolate, extension);
DCHECK(isolate->has_pending_exception() != result);
if (!result) {
// We print out the name of the extension that fail to install.
@@ -2914,6 +2926,7 @@ Genesis::Genesis(Isolate* isolate,
// We can only de-serialize a context if the isolate was initialized from
// a snapshot. Otherwise we have to build the context from scratch.
+ // Also create a context from scratch to expose natives, if required by flag.
Handle<FixedArray> outdated_contexts;
if (!isolate->initialized_from_snapshot() ||
!Snapshot::NewContextFromSnapshot(isolate, global_proxy,
« no previous file with comments | « src/array.js ('k') | src/contexts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698