diff options
Diffstat (limited to 'js/src/jit/WarpBuilderShared.cpp')
-rw-r--r-- | js/src/jit/WarpBuilderShared.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/js/src/jit/WarpBuilderShared.cpp b/js/src/jit/WarpBuilderShared.cpp new file mode 100644 index 0000000000..89e93d6150 --- /dev/null +++ b/js/src/jit/WarpBuilderShared.cpp @@ -0,0 +1,124 @@ +/* -*- 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/. */ + +#include "jit/WarpBuilderShared.h" + +#include "jit/MIRGenerator.h" +#include "jit/MIRGraph.h" + +using namespace js; +using namespace js::jit; + +WarpBuilderShared::WarpBuilderShared(WarpSnapshot& snapshot, + MIRGenerator& mirGen, + MBasicBlock* current_) + : snapshot_(snapshot), + mirGen_(mirGen), + alloc_(mirGen.alloc()), + current(current_) {} + +bool WarpBuilderShared::resumeAfter(MInstruction* ins, BytecodeLocation loc) { + // resumeAfter should only be used with effectful instructions. The only + // exception is MInt64ToBigInt, it's used to convert the result of a call into + // Wasm code so we attach the resume point to that instead of to the call. + MOZ_ASSERT(ins->isEffectful() || ins->isInt64ToBigInt()); + MOZ_ASSERT(!ins->isMovable()); + + MResumePoint* resumePoint = MResumePoint::New( + alloc(), ins->block(), loc.toRawBytecode(), ResumeMode::ResumeAfter); + if (!resumePoint) { + return false; + } + + ins->setResumePoint(resumePoint); + return true; +} + +MConstant* WarpBuilderShared::constant(const Value& v) { + MOZ_ASSERT_IF(v.isString(), v.toString()->isLinear()); + MOZ_ASSERT_IF(v.isGCThing(), !IsInsideNursery(v.toGCThing())); + + MConstant* cst = MConstant::New(alloc(), v); + current->add(cst); + return cst; +} + +void WarpBuilderShared::pushConstant(const Value& v) { + MConstant* cst = constant(v); + current->push(cst); +} + +MDefinition* WarpBuilderShared::unboxObjectInfallible(MDefinition* def, + IsMovable movable) { + if (def->type() == MIRType::Object) { + return def; + } + + if (def->type() != MIRType::Value) { + // Corner case: if the MIR node has a type other than Object or Value, this + // code isn't actually reachable and we expect an earlier guard to fail. + // Just insert a Box to satisfy MIR invariants. + MOZ_ASSERT(movable == IsMovable::No); + auto* box = MBox::New(alloc(), def); + current->add(box); + def = box; + } + + auto* unbox = MUnbox::New(alloc(), def, MIRType::Object, MUnbox::Infallible); + if (movable == IsMovable::No) { + unbox->setNotMovable(); + } + current->add(unbox); + return unbox; +} + +MCall* WarpBuilderShared::makeCall(CallInfo& callInfo, bool needsThisCheck, + WrappedFunction* target, bool isDOMCall) { + auto addUndefined = [this]() -> MConstant* { + return constant(UndefinedValue()); + }; + + return MakeCall(alloc(), addUndefined, callInfo, needsThisCheck, target, + isDOMCall); +} + +MInstruction* WarpBuilderShared::makeSpreadCall(CallInfo& callInfo, + bool needsThisCheck, + bool isSameRealm, + WrappedFunction* target) { + MOZ_ASSERT(callInfo.argFormat() == CallInfo::ArgFormat::Array); + MOZ_ASSERT_IF(needsThisCheck, !target); + + // Load dense elements of the argument array. + MElements* elements = MElements::New(alloc(), callInfo.arrayArg()); + current->add(elements); + + if (callInfo.constructing()) { + auto* newTarget = unboxObjectInfallible(callInfo.getNewTarget()); + auto* construct = + MConstructArray::New(alloc(), target, callInfo.callee(), elements, + callInfo.thisArg(), newTarget); + if (isSameRealm) { + construct->setNotCrossRealm(); + } + if (needsThisCheck) { + construct->setNeedsThisCheck(); + } + return construct; + } + + auto* apply = MApplyArray::New(alloc(), target, callInfo.callee(), elements, + callInfo.thisArg()); + + if (callInfo.ignoresReturnValue()) { + apply->setIgnoresReturnValue(); + } + if (isSameRealm) { + apply->setNotCrossRealm(); + } + MOZ_ASSERT(!needsThisCheck); + return apply; +} |