Bug 1499140 - Compile dynamic module import bytecode r=jandem
authorJon Coppeard <jcoppeard@mozilla.com>
Mon, 22 Oct 2018 11:28:17 +0100
changeset 490632 6592655e860e73040175e3a0de9d7a1ade2dea89
parent 490631 430db29f46858faff930e2ec3ed45fbf13a73a20
child 490633 41812db6cabaf796d6672786efa109ab771e3b2f
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersjandem
bugs1499140
milestone64.0a1
Bug 1499140 - Compile dynamic module import bytecode r=jandem
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineCompiler.h
js/src/jit/CodeGenerator.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
js/src/jit/Lowering.cpp
js/src/jit/MIR.h
js/src/jit/shared/LIR-shared.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1196,18 +1196,16 @@ BaselineCompiler::emitBody()
         }
 
         switch (op) {
           // ===== NOT Yet Implemented =====
           case JSOP_FORCEINTERPRETER:
             // Intentionally not implemented.
           case JSOP_SETINTRINSIC:
             // Run-once opcode during self-hosting initialization.
-          case JSOP_DYNAMIC_IMPORT:
-            // Dynamic module import.
           case JSOP_UNUSED126:
           case JSOP_UNUSED206:
           case JSOP_LIMIT:
             // === !! WARNING WARNING WARNING !! ===
             // Do you really want to sacrifice performance by not implementing
             // this operation in the BaselineCompiler?
             JitSpew(JitSpew_BaselineAbort, "Unhandled op: %s", CodeName[op]);
             return Method_CantCompile;
@@ -5441,8 +5439,33 @@ BaselineCompiler::emit_JSOP_IMPORTMETA()
     if (!callVM(GetOrCreateModuleMetaObjectInfo)) {
         return false;
     }
 
     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
     frame.push(R0);
     return true;
 }
+
+typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleValue, HandleValue);
+static const VMFunction StartDynamicModuleImportInfo =
+    FunctionInfo<StartDynamicModuleImportFn>(js::StartDynamicModuleImport,
+                                                "StartDynamicModuleImport");
+
+bool
+BaselineCompiler::emit_JSOP_DYNAMIC_IMPORT()
+{
+    RootedValue referencingPrivate(cx, FindScriptOrModulePrivateForScript(script));
+
+    // Put specifier value in R0.
+    frame.popRegsAndSync(1);
+
+    prepareVMCall();
+    pushArg(R0);
+    pushArg(referencingPrivate);
+    if (!callVM(StartDynamicModuleImportInfo)) {
+        return false;
+    }
+
+    masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
+    frame.push(R0);
+    return true;
+}
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -240,17 +240,18 @@ namespace jit {
     _(JSOP_TRY_DESTRUCTURING_ITERCLOSE) \
     _(JSOP_CHECKCLASSHERITAGE) \
     _(JSOP_INITHOMEOBJECT)     \
     _(JSOP_BUILTINPROTO)       \
     _(JSOP_OBJWITHPROTO)       \
     _(JSOP_FUNWITHPROTO)       \
     _(JSOP_CLASSCONSTRUCTOR)   \
     _(JSOP_DERIVEDCONSTRUCTOR) \
-    _(JSOP_IMPORTMETA)
+    _(JSOP_IMPORTMETA)         \
+    _(JSOP_DYNAMIC_IMPORT)
 
 class BaselineCompiler final
 {
     JSContext* cx;
     JSScript* script;
     jsbytecode* pc;
     StackMacroAssembler masm;
     bool ionCompileable_;
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3020,16 +3020,29 @@ static const VMFunction GetOrCreateModul
 
 void
 CodeGenerator::visitModuleMetadata(LModuleMetadata* lir)
 {
     pushArg(ImmPtr(lir->mir()->module()));
     callVM(GetOrCreateModuleMetaObjectInfo, lir);
 }
 
+typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleValue, HandleValue);
+static const VMFunction StartDynamicModuleImportInfo =
+    FunctionInfo<StartDynamicModuleImportFn>(js::StartDynamicModuleImport,
+                                                "StartDynamicModuleImport");
+
+void
+CodeGenerator::visitDynamicImport(LDynamicImport* lir)
+{
+    pushArg(ToValue(lir, LDynamicImport::SpecifierIndex));
+    pushArg(ToValue(lir, LDynamicImport::ReferencingPrivateIndex));
+    callVM(StartDynamicModuleImportInfo, lir);
+}
+
 typedef JSObject* (*LambdaFn)(JSContext*, HandleFunction, HandleObject);
 static const VMFunction LambdaInfo = FunctionInfo<LambdaFn>(js::Lambda, "Lambda");
 
 void
 CodeGenerator::visitLambdaForSingleton(LLambdaForSingleton* lir)
 {
     pushArg(ToRegister(lir->environmentChain()));
     pushArg(ImmGCPtr(lir->mir()->info().funUnsafe()));
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -16,16 +16,17 @@
 #include "jit/BaselineInspector.h"
 #include "jit/Ion.h"
 #include "jit/IonControlFlow.h"
 #include "jit/IonOptimizationLevels.h"
 #include "jit/JitSpewer.h"
 #include "jit/Lowering.h"
 #include "jit/MIRGraph.h"
 #include "vm/ArgumentsObject.h"
+#include "vm/EnvironmentObject.h"
 #include "vm/Opcodes.h"
 #include "vm/RegExpStatics.h"
 #include "vm/TraceLogging.h"
 
 #include "gc/Nursery-inl.h"
 #include "jit/CompileInfo-inl.h"
 #include "jit/shared/Lowering-shared-inl.h"
 #include "vm/BytecodeUtil-inl.h"
@@ -2484,16 +2485,19 @@ IonBuilder::inspectOpcode(JSOp op)
         arr->setImplicitlyUsedUnchecked();
         pushConstant(BooleanValue(false));
         return Ok();
       }
 
       case JSOP_IMPORTMETA:
         return jsop_importmeta();
 
+      case JSOP_DYNAMIC_IMPORT:
+        return jsop_dynamic_import();
+
       case JSOP_LOOPENTRY:
         return jsop_loopentry();
 
       // ===== NOT Yet Implemented =====
       // Read below!
 
       // With
       case JSOP_ENTERWITH:
@@ -2552,17 +2556,16 @@ IonBuilder::inspectOpcode(JSOp op)
       // Misc
       case JSOP_DELNAME:
       case JSOP_FINALLY:
       case JSOP_GETRVAL:
       case JSOP_GOSUB:
       case JSOP_RETSUB:
       case JSOP_SETINTRINSIC:
       case JSOP_THROWMSG:
-      case JSOP_DYNAMIC_IMPORT:
         // === !! WARNING WARNING WARNING !! ===
         // Do you really want to sacrifice performance by not implementing this
         // operation in the optimizing compiler?
         break;
 
       case JSOP_FORCEINTERPRETER:
         // Intentionally not implemented.
         break;
@@ -13824,16 +13827,30 @@ IonBuilder::jsop_importmeta()
     MOZ_ASSERT(module);
 
     MModuleMetadata* meta = MModuleMetadata::New(alloc(), module);
     current->add(meta);
     current->push(meta);
     return resumeAfter(meta);
 }
 
+AbortReasonOr<Ok>
+IonBuilder::jsop_dynamic_import()
+{
+    Value referencingPrivate = FindScriptOrModulePrivateForScript(script());
+    MConstant* ref = constant(referencingPrivate);
+
+    MDefinition* specifier = current->pop();
+
+    MDynamicImport* ins = MDynamicImport::New(alloc(), ref, specifier);
+    current->add(ins);
+    current->push(ins);
+    return resumeAfter(ins);
+}
+
 MInstruction*
 IonBuilder::addConvertElementsToDoubles(MDefinition* elements)
 {
     MInstruction* convert = MConvertElementsToDoubles::New(alloc(), elements);
     current->add(convert);
     return convert;
 }
 
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -588,16 +588,17 @@ class IonBuilder
     AbortReasonOr<Ok> jsop_debugger();
     AbortReasonOr<Ok> jsop_newtarget();
     AbortReasonOr<Ok> jsop_checkisobj(uint8_t kind);
     AbortReasonOr<Ok> jsop_checkiscallable(uint8_t kind);
     AbortReasonOr<Ok> jsop_checkobjcoercible();
     AbortReasonOr<Ok> jsop_pushcallobj();
     AbortReasonOr<Ok> jsop_implicitthis(PropertyName* name);
     AbortReasonOr<Ok> jsop_importmeta();
+    AbortReasonOr<Ok> jsop_dynamic_import();
 
     /* Inlining. */
 
     enum InliningStatus
     {
         InliningStatus_NotInlined,
         InliningStatus_WarmUpCountTooLow,
         InliningStatus_Inlined
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2598,16 +2598,25 @@ void
 LIRGenerator::visitModuleMetadata(MModuleMetadata* ins)
 {
     LModuleMetadata* lir = new(alloc()) LModuleMetadata();
     defineReturn(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
+LIRGenerator::visitDynamicImport(MDynamicImport* ins)
+{
+    LDynamicImport* lir = new(alloc()) LDynamicImport(useBoxAtStart(ins->referencingPrivate()),
+                                                      useBoxAtStart(ins->specifier()));
+    defineReturn(lir, ins);
+    assignSafepoint(lir, ins);
+}
+
+void
 LIRGenerator::visitLambda(MLambda* ins)
 {
     if (ins->info().singletonType || ins->info().useSingletonForClone) {
         // If the function has a singleton type, this instruction will only be
         // executed once so we don't bother inlining it.
         //
         // If UseSingletonForClone is true, we will assign a singleton type to
         // the clone and we have to clone the script, we can't do that inline.
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7814,16 +7814,32 @@ class MModuleMetadata : public MNullaryI
         return AliasSet::None();
     }
 
     bool appendRoots(MRootList& roots) const override {
         return roots.append(module_);
     }
 };
 
+class MDynamicImport : public MBinaryInstruction,
+                       public BoxInputsPolicy::Data
+{
+    explicit MDynamicImport(MDefinition* referencingPrivate, MDefinition* specifier)
+      : MBinaryInstruction(classOpcode, referencingPrivate, specifier)
+    {
+        setResultType(MIRType::Object);
+    }
+
+  public:
+    INSTRUCTION_HEADER(DynamicImport)
+    TRIVIAL_NEW_WRAPPERS
+    NAMED_OPERANDS((0, referencingPrivate))
+    NAMED_OPERANDS((1, specifier))
+};
+
 struct LambdaFunctionInfo
 {
     // The functions used in lambdas are the canonical original function in
     // the script, and are immutable except for delazification. Record this
     // information while still on the main thread to avoid races.
   private:
     CompilerFunction fun_;
 
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -4898,16 +4898,37 @@ class LModuleMetadata : public LCallInst
         return mir_->toModuleMetadata();
     }
 
     LModuleMetadata()
       : LCallInstructionHelper(classOpcode)
     {}
 };
 
+class LDynamicImport : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
+{
+  public:
+    LIR_HEADER(DynamicImport)
+
+    static const size_t ReferencingPrivateIndex = 0;
+    static const size_t SpecifierIndex = BOX_PIECES;
+
+    explicit LDynamicImport(const LBoxAllocation& referencingPrivate,
+                            const LBoxAllocation& specifier)
+      : LCallInstructionHelper(classOpcode)
+    {
+        setBoxOperand(ReferencingPrivateIndex, referencingPrivate);
+        setBoxOperand(SpecifierIndex, specifier);
+    }
+
+    const MDynamicImport* mir() const {
+        return mir_->toDynamicImport();
+    }
+};
+
 class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LambdaForSingleton)
 
     explicit LLambdaForSingleton(const LAllocation& envChain)
       : LCallInstructionHelper(classOpcode)
     {