Exemple #1
0
BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator &activations,
                                   BailoutStack *bailout)
  : machine_(bailout->machine())
{
    uint8_t *sp = bailout->parentStackPointer();
    framePointer_ = sp + bailout->frameSize();
    topFrameSize_ = framePointer_ - sp;

    JSScript *script = ScriptFromCalleeToken(((JitFrameLayout *) framePointer_)->calleeToken());
    JitActivation *activation = activations.activation()->asJit();
    topIonScript_ = script->ionScript();

    attachOnJitActivation(activations);

    if (bailout->frameClass() == FrameSizeClass::None()) {
        snapshotOffset_ = bailout->snapshotOffset();
        return;
    }

    // Compute the snapshot offset from the bailout ID.
    JSRuntime *rt = activation->compartment()->runtimeFromMainThread();
    JitCode *code = rt->jitRuntime()->getBailoutTable(bailout->frameClass());
    uintptr_t tableOffset = bailout->tableOffset();
    uintptr_t tableStart = reinterpret_cast<uintptr_t>(Assembler::BailoutTableStart(code->raw()));

    MOZ_ASSERT(tableOffset >= tableStart &&
               tableOffset < tableStart + code->instructionsSize());
    MOZ_ASSERT((tableOffset - tableStart) % BAILOUT_TABLE_ENTRY_SIZE == 0);

    uint32_t bailoutId = ((tableOffset - tableStart) / BAILOUT_TABLE_ENTRY_SIZE) - 1;
    MOZ_ASSERT(bailoutId < BAILOUT_TABLE_SIZE);

    snapshotOffset_ = topIonScript_->bailoutToSnapshot(bailoutId);
}
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
                                       BailoutStack *bailout)
  : IonFrameIterator(activations),
    machine_(bailout->machine())
{
    uint8_t *sp = bailout->parentStackPointer();
    uint8_t *fp = sp + bailout->frameSize();

    current_ = fp;
    type_ = IonFrame_OptimizedJS;
    topFrameSize_ = current_ - sp;
    topIonScript_ = script()->ionScript();

    if (bailout->frameClass() == FrameSizeClass::None()) {
        snapshotOffset_ = bailout->snapshotOffset();
        return;
    }

    // Compute the snapshot offset from the bailout ID.
    JitActivation *activation = activations.activation()->asJit();
    JSRuntime *rt = activation->compartment()->runtimeFromMainThread();
    JitCode *code = rt->jitRuntime()->getBailoutTable(bailout->frameClass());
    uintptr_t tableOffset = bailout->tableOffset();
    uintptr_t tableStart = reinterpret_cast<uintptr_t>(code->raw());

    JS_ASSERT(tableOffset >= tableStart &&
              tableOffset < tableStart + code->instructionsSize());
    JS_ASSERT((tableOffset - tableStart) % BAILOUT_TABLE_ENTRY_SIZE == 0);

    uint32_t bailoutId = ((tableOffset - tableStart) / BAILOUT_TABLE_ENTRY_SIZE) - 1;
    JS_ASSERT(bailoutId < BAILOUT_TABLE_SIZE);

    snapshotOffset_ = topIonScript_->bailoutToSnapshot(bailoutId);
}
Exemple #3
0
BailoutEnvironment::BailoutEnvironment(JitCompartment *ion, void **sp)
  : sp_(sp)
{
    bailout_ = reinterpret_cast<ExtendedBailoutStack *>(sp);

    if (bailout_->frameClass() != FrameSizeClass::None()) {
        frameSize_ = bailout_->frameSize();
        frame_ = &sp_[sizeof(BailoutStack) / sizeof(void *)];

        // Compute the bailout ID.
        JitCode *code = ion->getBailoutTable(bailout_->frameClass());
        uintptr_t tableOffset = bailout_->tableOffset();
        uintptr_t tableStart = reinterpret_cast<uintptr_t>(code->raw());

        JS_ASSERT(tableOffset >= tableStart &&
                  tableOffset < tableStart + code->instructionsSize());
        JS_ASSERT((tableOffset - tableStart) % BAILOUT_TABLE_ENTRY_SIZE == 0);

        bailoutId_ = ((tableOffset - tableStart) / BAILOUT_TABLE_ENTRY_SIZE) - 1;
        JS_ASSERT(bailoutId_ < BAILOUT_TABLE_SIZE);
    } else {
        frameSize_ = bailout_->frameSize();
        frame_ = &sp_[sizeof(ExtendedBailoutStack) / sizeof(void *)];
    }
}
Exemple #4
0
JitCode*
Linker::newCode(JSContext* cx, CodeKind kind)
{
    JS::AutoAssertNoGC nogc(cx);
    if (masm.oom())
        return fail(cx);

    masm.performPendingReadBarriers();

    static const size_t ExecutableAllocatorAlignment = sizeof(void*);
    static_assert(CodeAlignment >= ExecutableAllocatorAlignment,
                  "Unexpected alignment requirements");

    // We require enough bytes for the code, header, and worst-case alignment padding.
    size_t bytesNeeded = masm.bytesNeeded() +
                         sizeof(JitCodeHeader) +
                         (CodeAlignment - ExecutableAllocatorAlignment);
    if (bytesNeeded >= MAX_BUFFER_SIZE)
        return fail(cx);

    // ExecutableAllocator requires bytesNeeded to be aligned.
    bytesNeeded = AlignBytes(bytesNeeded, ExecutableAllocatorAlignment);

    ExecutablePool* pool;
    uint8_t* result =
        (uint8_t*)cx->runtime()->jitRuntime()->execAlloc().alloc(cx, bytesNeeded, &pool, kind);
    if (!result)
        return fail(cx);

    // The JitCodeHeader will be stored right before the code buffer.
    uint8_t* codeStart = result + sizeof(JitCodeHeader);

    // Bump the code up to a nice alignment.
    codeStart = (uint8_t*)AlignBytes((uintptr_t)codeStart, CodeAlignment);
    MOZ_ASSERT(codeStart + masm.bytesNeeded() <= result + bytesNeeded);
    uint32_t headerSize = codeStart - result;
    JitCode* code = JitCode::New<NoGC>(cx, codeStart, bytesNeeded - headerSize,
                                       headerSize, pool, kind);
    if (!code)
        return fail(cx);
    if (masm.oom())
        return fail(cx);
    awjc.emplace(result, bytesNeeded);
    code->copyFrom(masm);
    masm.link(code);
    if (masm.embedsNurseryPointers())
        cx->runtime()->gc.storeBuffer().putWholeCell(code);
    return code;
}
Exemple #5
0
JitCode*
Linker::newCode(JSContext* cx, CodeKind kind, bool hasPatchableBackedges /* = false */)
{
    MOZ_ASSERT(masm.numAsmJSAbsoluteAddresses() == 0);
    MOZ_ASSERT_IF(hasPatchableBackedges, kind == ION_CODE);

    gc::AutoSuppressGC suppressGC(cx);
    if (masm.oom())
        return fail(cx);

    ExecutablePool* pool;
    size_t bytesNeeded = masm.bytesNeeded() + sizeof(JitCode*) + CodeAlignment;
    if (bytesNeeded >= MAX_BUFFER_SIZE)
        return fail(cx);

    // ExecutableAllocator requires bytesNeeded to be word-size aligned.
    bytesNeeded = AlignBytes(bytesNeeded, sizeof(void*));

    ExecutableAllocator& execAlloc = hasPatchableBackedges
        ? cx->runtime()->jitRuntime()->backedgeExecAlloc()
        : cx->runtime()->jitRuntime()->execAlloc();
    uint8_t* result = (uint8_t*)execAlloc.alloc(bytesNeeded, &pool, kind);
    if (!result)
        return fail(cx);

    // The JitCode pointer will be stored right before the code buffer.
    uint8_t* codeStart = result + sizeof(JitCode*);

    // Bump the code up to a nice alignment.
    codeStart = (uint8_t*)AlignBytes((uintptr_t)codeStart, CodeAlignment);
    uint32_t headerSize = codeStart - result;
    JitCode* code = JitCode::New<allowGC>(cx, codeStart, bytesNeeded - headerSize,
                                          headerSize, pool, kind);
    if (!code)
        return nullptr;
    if (masm.oom())
        return fail(cx);
    awjc.emplace(result, bytesNeeded);
    code->copyFrom(masm);
    masm.link(code);
    if (masm.embedsNurseryPointers())
        cx->runtime()->gc.storeBuffer.putWholeCell(code);
    return code;
}
static bool Execute(JSContext* cx, MacroAssembler& masm)
{
    AllocatableRegisterSet regs(RegisterSet::Volatile());
    LiveRegisterSet save(regs.asLiveSet());
    masm.PopRegsInMask(save);
    masm.ret(); // Add return statement to be sure.

    if (masm.oom())
        return false;

    Linker linker(masm);
    JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
    if (!code)
        return false;
    if (!ExecutableAllocator::makeExecutable(code->raw(), code->bufferSize()))
        return false;

    EnterTest test = code->as<EnterTest>();
    test();
    return true;
}
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
                                       BailoutStack *bailout)
  : JitFrameIterator(activations),
    machine_(bailout->machine())
{
    uint8_t *sp = bailout->parentStackPointer();
    uint8_t *fp = sp + bailout->frameSize();

    kind_ = Kind_BailoutIterator;
    current_ = fp;
    type_ = JitFrame_IonJS;
    topFrameSize_ = current_ - sp;
    switch (mode_) {
      case SequentialExecution: topIonScript_ = script()->ionScript(); break;
      case ParallelExecution: topIonScript_ = script()->parallelIonScript(); break;
      default: MOZ_ASSUME_UNREACHABLE("No such execution mode");
    }

    if (bailout->frameClass() == FrameSizeClass::None()) {
        snapshotOffset_ = bailout->snapshotOffset();
        return;
    }

    // Compute the snapshot offset from the bailout ID.
    JitActivation *activation = activations.activation()->asJit();
    JSRuntime *rt = activation->compartment()->runtimeFromMainThread();
    JitCode *code = rt->jitRuntime()->getBailoutTable(bailout->frameClass());
    uintptr_t tableOffset = bailout->tableOffset();
    uintptr_t tableStart = reinterpret_cast<uintptr_t>(Assembler::BailoutTableStart(code->raw()));

    JS_ASSERT(tableOffset >= tableStart &&
              tableOffset < tableStart + code->instructionsSize());
    JS_ASSERT((tableOffset - tableStart) % BAILOUT_TABLE_ENTRY_SIZE == 0);

    uint32_t bailoutId = ((tableOffset - tableStart) / BAILOUT_TABLE_ENTRY_SIZE) - 1;
    JS_ASSERT(bailoutId < BAILOUT_TABLE_SIZE);

    snapshotOffset_ = topIonScript_->bailoutToSnapshot(bailoutId);
}