[modules] Optimize import.meta in the interpreter

Use an intrinsic for GetImportMetaObject and generate bytecode for the
case where import.meta has been initialized already. This way the
runtime method will only be called once per module.

Bug: v8:6693
Change-Id: If661e88e6accfb1c5795e37a80582d04f6dd87dd
Reviewed-on: https://chromium-review.googlesource.com/716536
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48801}
This commit is contained in:
Jan Krems 2017-10-20 11:10:35 -07:00 committed by Commit Bot
parent 35b6aa3849
commit 8683248625
7 changed files with 70 additions and 2 deletions

View File

@ -31,6 +31,7 @@ StrongLoop, Inc. <*@strongloop.com>
Facebook, Inc. <*@fb.com>
Facebook, Inc. <*@oculus.com>
Vewd Software AS <*@vewd.com>
Groupon <*@groupon.com>
Aaron Bieber <deftly@gmail.com>
Abdulla Kamar <abdulla.kamar@gmail.com>
@ -75,6 +76,7 @@ Ioseb Dzmanashvili <ioseb.dzmanashvili@gmail.com>
Isiah Meadows <impinball@gmail.com>
Jaime Bernardo <jaime@janeasystems.com>
Jan de Mooij <jandemooij@gmail.com>
Jan Krems <jan.krems@gmail.com>
Jay Freeman <saurik@saurik.com>
James Pike <g00gle@chilon.net>
Jianghua Yang <jianghua.yjh@alibaba-inc.com>

View File

@ -1678,6 +1678,33 @@ TNode<Context> CodeStubAssembler::LoadNativeContext(
LoadContextElement(context, Context::NATIVE_CONTEXT_INDEX));
}
TNode<Context> CodeStubAssembler::LoadModuleContext(
SloppyTNode<Context> context) {
Node* module_map = LoadRoot(Heap::kModuleContextMapRootIndex);
Variable cur_context(this, MachineRepresentation::kTaggedPointer);
cur_context.Bind(context);
Label context_found(this);
Variable* context_search_loop_variables[1] = {&cur_context};
Label context_search(this, 1, context_search_loop_variables);
// Loop until cur_context->map() is module_map.
Goto(&context_search);
BIND(&context_search);
{
CSA_ASSERT(this, Word32BinaryNot(IsNativeContext(cur_context.value())));
GotoIf(WordEqual(LoadMap(cur_context.value()), module_map), &context_found);
cur_context.Bind(
LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX));
Goto(&context_search);
}
BIND(&context_found);
return UncheckedCast<Context>(cur_context.value());
}
TNode<Map> CodeStubAssembler::LoadJSArrayElementsMap(
SloppyTNode<Int32T> kind, SloppyTNode<Context> native_context) {
CSA_ASSERT(this, IsFastElementsKind(kind));

View File

@ -594,6 +594,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
int slot_index,
SloppyTNode<Object> value);
TNode<Context> LoadNativeContext(SloppyTNode<Context> context);
// Calling this is only valid if there's a module context in the chain.
TNode<Context> LoadModuleContext(SloppyTNode<Context> context);
TNode<Map> LoadJSArrayElementsMap(ElementsKind kind,
SloppyTNode<Context> native_context);

View File

@ -11,6 +11,8 @@
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter-assembler.h"
#include "src/interpreter/interpreter-intrinsics.h"
#include "src/objects-inl.h"
#include "src/objects/module.h"
namespace v8 {
namespace internal {
@ -427,6 +429,28 @@ Node* IntrinsicsGenerator::GeneratorClose(Node* args_reg, Node* arg_count,
return __ UndefinedConstant();
}
Node* IntrinsicsGenerator::GetImportMetaObject(Node* args_reg, Node* arg_count,
Node* context) {
Node* const module_context = __ LoadModuleContext(context);
Node* const module =
__ LoadContextElement(module_context, Context::EXTENSION_INDEX);
Node* const import_meta =
__ LoadObjectField(module, Module::kImportMetaOffset);
InterpreterAssembler::Variable return_value(assembler_,
MachineRepresentation::kTagged);
return_value.Bind(import_meta);
InterpreterAssembler::Label end(assembler_);
__ GotoIfNot(__ IsTheHole(import_meta), &end);
return_value.Bind(__ CallRuntime(Runtime::kGetImportMetaObject, context));
__ Goto(&end);
__ BIND(&end);
return return_value.value();
}
Node* IntrinsicsGenerator::AsyncGeneratorReject(Node* input, Node* arg_count,
Node* context) {
return IntrinsicAsBuiltinCall(input, context,

View File

@ -22,6 +22,7 @@ namespace interpreter {
V(GeneratorGetResumeMode, generator_get_resume_mode, 1) \
V(GeneratorGetInputOrDebugPos, generator_get_input_or_debug_pos, 1) \
V(GeneratorClose, generator_close, 1) \
V(GetImportMetaObject, get_import_meta_object, 0) \
V(Call, call, -1) \
V(ClassOf, class_of, 1) \
V(CreateIterResultObject, create_iter_result_object, 2) \

View File

@ -385,7 +385,7 @@ Expression* Parser::FunctionSentExpression(int pos) {
Expression* Parser::ImportMetaExpression(int pos) {
return factory()->NewCallRuntime(
Runtime::kGetImportMetaObject,
Runtime::kInlineGetImportMetaObject,
new (zone()) ZoneList<Expression*>(0, zone()), pos);
}

View File

@ -3,7 +3,7 @@
// found in the LICENSE file.
// MODULE
// Flags: --harmony-import-meta
// Flags: --harmony-import-meta --no-lazy
import foreign, { url as otherUrl } from './modules-skip-export-import-meta.js';
@ -11,6 +11,18 @@ assertEquals("object", typeof import.meta);
assertEquals(null, Object.getPrototypeOf(import.meta));
assertSame(import.meta, import.meta);
const loadImportMetaArrow = () => import.meta;
assertSame(loadImportMetaArrow(), import.meta);
function loadImportMetaFn() {
try {
throw new Error('force catch code path for nested context');
} catch (e) {
return import.meta;
}
}
loadImportMetaFn();
assertSame(loadImportMetaFn(), import.meta);
// This property isn't part of the spec itself but is mentioned as an example
assertMatches(/\/modules-import-meta\.js$/, import.meta.url);