Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions js/moz.configure
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,21 @@ set_config(
depends_if("--enable-portable-baseline-interp-force")(lambda _: True),
)

# weval support (ahead-of-time interpreter compilation in Wasm) for PBL.
option(
"--enable-pbl-weval",
default=False,
help="{Support|Do not support} wevaling the PBL interpreter",
)

@depends("--enable-portable-baseline-interp", "--enable-pbl-weval")
def js_pbl_weval(pbl, weval):
if pbl and weval:
return True

set_define("ENABLE_JS_PBL_WEVAL", js_pbl_weval)
set_config("ENABLE_JS_PBL_WEVAL", js_pbl_weval)

# Enable ahead-of-time-known preloaded IC bodies.
option(
"--enable-aot-ics",
Expand Down
7 changes: 6 additions & 1 deletion js/src/jit-test/tests/gc/bug-1791975.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
// |jit-test| skip-if: !('oomAtAllocation' in this)
// |jit-test| skip-if: !('oomAtAllocation' in this) || getBuildConfiguration('pbl')
//
// We skip this test under PBL-debug builds because it seems to have a
// nondeterministic OOM failure that we can't reproduce locally. Other tests
// provide coverage of OOM handling generally so we don't lose too much
// (hopefully!) by skipping this one.

gczeal(10, 10);
try {
Expand Down
13 changes: 13 additions & 0 deletions js/src/jit/BaselineCacheIRCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "util/Unicode.h"
#include "vm/PortableBaselineInterpret.h"
#include "vm/StaticStrings.h"
#include "vm/Weval.h"

#include "jit/JitScript-inl.h"
#include "jit/MacroAssembler-inl.h"
Expand Down Expand Up @@ -2612,6 +2613,11 @@ static bool LookupOrCompileStub(JSContext* cx, CacheKind kind,
/* stubCode = */ nullptr)) {
return false;
}

#ifdef ENABLE_JS_PBL_WEVAL
// Register for weval specialization, if enabled.
js::pbl::EnqueueICStubSpecialization(stubInfo);
#endif
}
MOZ_ASSERT_IF(IsBaselineInterpreterEnabled(), code);
MOZ_ASSERT(stubInfo);
Expand Down Expand Up @@ -2739,7 +2745,14 @@ ICAttachResult js::jit::AttachBaselineCacheIRStub(
newStub->setTypeData(writer.typeData());

#ifdef ENABLE_PORTABLE_BASELINE_INTERP
# ifdef ENABLE_JS_PBL_WEVAL
newStub->updateRawJitCode(
(stubInfo->hasWeval() && stubInfo->weval().func)
? reinterpret_cast<uint8_t*>(stubInfo->weval().func)
: pbl::GetICInterpreter());
# else
newStub->updateRawJitCode(pbl::GetICInterpreter());
# endif
#endif

stub->addNewStub(icEntry, newStub);
Expand Down
10 changes: 10 additions & 0 deletions js/src/jit/CacheIRCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "vm/GetterSetter.h"
#include "vm/Interpreter.h"
#include "vm/Uint8Clamped.h"
#include "vm/Weval.h"

#include "builtin/Boolean-inl.h"
#include "jit/MacroAssembler-inl.h"
Expand Down Expand Up @@ -1260,6 +1261,15 @@ ICCacheIRStub* ICCacheIRStub::clone(JSRuntime* rt, ICStubSpace& newSpace) {
return newStub;
}

#ifdef ENABLE_JS_PBL_WEVAL
Weval& CacheIRStubInfo::weval() {
if (!weval_) {
weval_ = MakeUnique<Weval>();
}
return *weval_;
}
#endif

template <typename T>
static inline bool ShouldTraceWeakEdgeInStub(JSTracer* trc) {
if constexpr (std::is_same_v<T, IonICStub>) {
Expand Down
13 changes: 13 additions & 0 deletions js/src/jit/CacheIRCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class FixedLengthTypedArrayObject;
class TypedArrayObject;
enum class UnaryMathFunction : uint8_t;

#ifdef ENABLE_JS_PBL_WEVAL
struct Weval;
#endif

namespace jit {

class BaselineCacheIRCompiler;
Expand Down Expand Up @@ -1321,6 +1325,10 @@ class CacheIRStubInfo {
uint8_t stubDataOffset_;
bool makesGCCalls_;

#ifdef ENABLE_JS_PBL_WEVAL
UniquePtr<Weval> weval_ = {};
#endif

CacheIRStubInfo(CacheKind kind, ICStubEngine engine, bool makesGCCalls,
uint32_t stubDataOffset, uint32_t codeLength);

Expand Down Expand Up @@ -1395,6 +1403,11 @@ class CacheIRStubInfo {

void replaceStubRawWord(uint8_t* stubData, uint32_t offset, uintptr_t oldWord,
uintptr_t newWord) const;

#ifdef ENABLE_JS_PBL_WEVAL
bool hasWeval() const { return weval_.get() != nullptr; }
Weval& weval();
#endif
};

template <typename T>
Expand Down
5 changes: 5 additions & 0 deletions js/src/jit/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -311,3 +311,8 @@ if CONFIG["ENABLE_JS_AOT_ICS"]:

if CONFIG["FUZZING_INTERFACES"] or CONFIG["FUZZING_JS_FUZZILLI"]:
include("/tools/fuzzing/libfuzzer-config.mozbuild")

if CONFIG["ENABLE_JS_PBL_WEVAL"]:
LOCAL_INCLUDES += [
"../../../third_party/weval"
]
5 changes: 5 additions & 0 deletions js/src/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -676,3 +676,8 @@ if CONFIG["JS_HAS_INTL_API"]:
]

USE_LIBS += ["intlcomponents"]

if CONFIG["ENABLE_JS_PBL_WEVAL"]:
LOCAL_INCLUDES += [
"../../third_party/weval"
]
11 changes: 11 additions & 0 deletions js/src/vm/JSScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
#include "vm/StringType.h" // JSString, JSAtom
#include "vm/Time.h" // AutoIncrementalTimer
#include "vm/ToSource.h" // JS::ValueToSource
#include "vm/Weval.h"
#ifdef MOZ_VTUNE
# include "vtune/VTuneWrapper.h"
#endif
Expand Down Expand Up @@ -2505,6 +2506,10 @@ bool JSScript::fullyInitFromStencil(
}
}

#ifdef ENABLE_JS_PBL_WEVAL
pbl::EnqueueScriptSpecialization(script);
#endif

return true;
}

Expand Down Expand Up @@ -3720,3 +3725,9 @@ JS::ubi::Base::Size JS::ubi::Concrete<BaseScript>::size(
const char* JS::ubi::Concrete<BaseScript>::scriptFilename() const {
return get().filename();
}

#ifdef ENABLE_JS_PBL_WEVAL
void BaseScript::allocWeval() {
weval_ = MakeUnique<Weval>();
}
#endif
20 changes: 20 additions & 0 deletions js/src/vm/JSScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ struct CompilationStencilMerger;
class StencilXDR;
} // namespace frontend

struct Weval;

class ScriptCounts {
public:
typedef mozilla::Vector<PCCounts, 0, SystemAllocPolicy> PCCountsVector;
Expand Down Expand Up @@ -1490,6 +1492,13 @@ class BaseScript : public gc::TenuredCellWithNonGCPointer<uint8_t> {
// will be nullptr.
RefPtr<js::SharedImmutableScriptData> sharedData_ = {};

#ifdef ENABLE_JS_PBL_WEVAL
// Specialized function generated by partial-evaluation tool
// `weval`, if any. Indirected via a `UniquePtr` to keep a stable
// address across GCs.
UniquePtr<Weval> weval_ = {};
#endif

// End of fields.

BaseScript(uint8_t* stubEntry, JSFunction* function,
Expand Down Expand Up @@ -1669,6 +1678,17 @@ class BaseScript : public gc::TenuredCellWithNonGCPointer<uint8_t> {
#if defined(DEBUG) || defined(JS_JITSPEW)
void dumpStringContent(js::GenericPrinter& out) const;
#endif

#ifdef ENABLE_JS_PBL_WEVAL
bool hasWeval() const { return weval_.get() != nullptr; }
Weval& weval() {
if (!weval_) {
allocWeval();
}
return *weval_;
}
void allocWeval();
#endif
};

extern void SweepScriptData(JSRuntime* rt);
Expand Down
133 changes: 133 additions & 0 deletions js/src/vm/PortableBaselineInterpret-weval-defs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef PortableBaselineInerpret_weval_defs_h
#define PortableBaselineInerpret_weval_defs_h

/* Basic definitions for PBL's internals that can be swapped out as
* needed to handle interpreter details differently.
*
* Meant to be included only from PortableBaselineInterpret.cpp. */

#define PBL_HYBRID_ICS_DEFAULT false

#define PBL_CALL_IC(jitcode, ctx, stubvalue, result, arg0, arg1, arg2value, \
hasarg2) \
do { \
if (hasarg2) { \
ctx.arg2 = arg2value; \
} \
ICStubFunc func = reinterpret_cast<ICStubFunc>(jitcode); \
result = func(arg0, arg1, stubvalue, ctx); \
} while (0)

#define PBL_CALL_INTERP(result, script, interp, ...) \
if (script->hasWeval() && script->weval().func) { \
result = (reinterpret_cast<PBIFunc>(script->weval().func))(__VA_ARGS__); \
} else { \
result = interp(__VA_ARGS__); \
}

#define PBL_ESTABLISH_STUBINFO_CODE(Specialized, stubInfo, code) \
if (!Specialized) { \
stubInfo = cstub->stubInfo(); \
code = stubInfo->code(); \
} else { \
stubInfo = reinterpret_cast<const CacheIRStubInfo*>( \
weval_read_specialization_global(0)); \
code = reinterpret_cast<uint8_t*>(weval_read_specialization_global(1)); \
}

#define READ_REG(reg) \
(Specialized ? weval_read_reg((reg)) : ctx.icregs.icVals[(reg)])
#define WRITE_REG(reg, value, tagtype) \
if (Specialized) { \
weval_write_reg((reg), (value)); \
weval_write_reg((reg) + ICRegs::kMaxICVals, uint64_t(JSVAL_TAG_##tagtype) \
<< JSVAL_TAG_SHIFT); \
} else { \
ctx.icregs.icVals[(reg)] = (value); \
ctx.icregs.icTags[(reg)] = uint64_t(JSVAL_TAG_##tagtype) \
<< JSVAL_TAG_SHIFT; \
}

#define READ_VALUE_REG(reg) \
Value::fromRawBits( \
Specialized ? (weval_read_reg((reg) + ICRegs::kMaxICVals) | \
weval_read_reg((reg))) \
: (ctx.icregs.icTags[(reg)] | ctx.icregs.icVals[(reg)]))
#define WRITE_VALUE_REG(reg, value) \
if (Specialized) { \
weval_write_reg((reg), (value).asRawBits()); \
weval_write_reg((reg) + ICRegs::kMaxICVals, 0); \
} else { \
ctx.icregs.icVals[(reg)] = (value).asRawBits(); \
ctx.icregs.icTags[(reg)] = 0; \
}

#define PBL_PUSH_CTX(ctx) weval::push_context(reinterpret_cast<uint32_t>(ctx));

#define PBL_UPDATE_CTX(ctx) \
weval::update_context(reinterpret_cast<uint32_t>(ctx));

#define PBL_POP_CTX() \
weval::pop_context();

#define VIRTPUSH(value) \
if (Specialized) { \
--sp; \
weval_push_stack(reinterpret_cast<uint64_t*>(sp), (value).asUInt64()); \
} else { \
*--sp = (value); \
}
#define VIRTPOP() \
(Specialized ? ({ \
uint64_t* ptr = reinterpret_cast<uint64_t*>(sp++); \
StackVal(weval_pop_stack(ptr)); \
}) \
: *sp++)
#define VIRTSP(index) \
(Specialized ? StackVal(weval_read_stack( \
reinterpret_cast<uint64_t*>(&sp[(index)]), (index))) \
: sp[(index)])
#define VIRTSPWRITE(index, value) \
if (Specialized) { \
weval_write_stack(reinterpret_cast<uint64_t*>(&sp[(index)]), (index), \
(value).asUInt64()); \
} else { \
sp[(index)] = (value); \
}
#define SYNCSP() \
if (Specialized) { \
weval_sync_stack(); \
}
#define SETLOCAL(i, value) \
if (Specialized) { \
weval_write_local(reinterpret_cast<uint64_t*>(&frame->unaliasedLocal(i)), \
i, (value).asRawBits()); \
} else { \
frame->unaliasedLocal(i) = value; \
}
#define GETLOCAL(i) \
(Specialized \
? Value::fromRawBits(weval_read_local( \
reinterpret_cast<uint64_t*>(&frame->unaliasedLocal(i)), i)) \
: frame->unaliasedLocal(i))

#define PBL_SETUP_INTERP_INPUTS(argsObjAliasesFormals, nfixed) \
argsObjAliasesFormals = Specialized \
? (weval_read_specialization_global(0) != 0) \
: frame->script()->argsObjAliasesFormals(); \
nfixed = Specialized ? weval_read_specialization_global(1) \
: frame->script()->nfixed();

#define PBL_SPECIALIZE_VALUE(i, low, high) \
int32_t(weval_specialize_value(uint32_t(i), 0, uint32_t(high - low + 1)));

#define PBL_SCRIPT_HAS_SPECIALIZATION(script) \
(script->hasWeval() && script->weval().func)

#endif /* PortableBaselineInerpret_defs_h */
Loading