зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1699271 - Part 11: Add autogeneration for MIR ops that take arguments. r=iain
Differential Revision: https://phabricator.services.mozilla.com/D116775
This commit is contained in:
Родитель
442a2844ac
Коммит
c3b56668cb
|
@ -98,9 +98,25 @@ mir_base_class = [
|
|||
]
|
||||
|
||||
|
||||
gc_pointer_types = [
|
||||
"JSObject*",
|
||||
"NativeObject*",
|
||||
"JSFunction*",
|
||||
"BaseScript*",
|
||||
"PropertyName*",
|
||||
"Shape*",
|
||||
"GetterSetter*",
|
||||
"JSAtom*",
|
||||
"ClassBodyScope*",
|
||||
"NamedLambdaObject*",
|
||||
"RegExpObject*",
|
||||
]
|
||||
|
||||
|
||||
def gen_mir_class(
|
||||
name,
|
||||
operands,
|
||||
arguments,
|
||||
no_type_policy,
|
||||
result,
|
||||
guard,
|
||||
|
@ -169,12 +185,28 @@ def gen_mir_class(
|
|||
assert type_policy
|
||||
type_policy = ", " + type_policy
|
||||
code = "class {} : public {}{} {{\\\n".format(class_name, base_class, type_policy)
|
||||
|
||||
# Arguments to class constructor that require accessors.
|
||||
mir_args = []
|
||||
if arguments:
|
||||
for arg_name in arguments:
|
||||
arg_type_sig = arguments[arg_name]
|
||||
mir_args.append(arg_type_sig + " " + arg_name)
|
||||
if arg_type_sig in gc_pointer_types:
|
||||
code += " CompilerGCPointer<" + arg_type_sig + ">"
|
||||
else:
|
||||
code += " " + arg_type_sig
|
||||
code += " " + arg_name + "_;\\\n"
|
||||
|
||||
code += " explicit {}({}) : {}(classOpcode{})".format(
|
||||
class_name,
|
||||
", ".join(mir_operands),
|
||||
", ".join(mir_operands + mir_args),
|
||||
base_class,
|
||||
"".join(mir_base_class_operands),
|
||||
)
|
||||
if arguments:
|
||||
for arg_name in arguments:
|
||||
code += ", " + arg_name + "_(" + arg_name + ")"
|
||||
code += " {\\\n"
|
||||
if guard:
|
||||
code += " setGuard();\\\n"
|
||||
|
@ -182,7 +214,12 @@ def gen_mir_class(
|
|||
code += " setMovable();\\\n"
|
||||
if result:
|
||||
code += " setResultType(MIRType::{});\\\n".format(result)
|
||||
code += " }}\\\n public:\\\n INSTRUCTION_HEADER({})\\\n".format(name)
|
||||
code += " }\\\n public:\\\n"
|
||||
if arguments:
|
||||
for arg_name in arguments:
|
||||
code += " " + arguments[arg_name] + " " + arg_name + "() const { "
|
||||
code += "return " + arg_name + "_; }\\\n"
|
||||
code += " INSTRUCTION_HEADER({})\\\n".format(name)
|
||||
code += " TRIVIAL_NEW_WRAPPERS\\\n"
|
||||
if named_operands:
|
||||
code += " NAMED_OPERANDS({})\\\n".format(", ".join(named_operands))
|
||||
|
@ -251,6 +288,9 @@ def generate_mir_header(c_out, yaml_path):
|
|||
operands = op.get("operands", None)
|
||||
assert operands is None or isinstance(operands, OrderedDict)
|
||||
|
||||
arguments = op.get("arguments", None)
|
||||
assert arguments is None or isinstance(arguments, OrderedDict)
|
||||
|
||||
no_type_policy = op.get("type_policy", None)
|
||||
assert no_type_policy is None or no_type_policy == "none"
|
||||
|
||||
|
@ -291,6 +331,7 @@ def generate_mir_header(c_out, yaml_path):
|
|||
code = gen_mir_class(
|
||||
name,
|
||||
operands,
|
||||
arguments,
|
||||
no_type_policy,
|
||||
result,
|
||||
guard,
|
||||
|
|
|
@ -343,16 +343,16 @@ void LIRGenerator::visitGetInlinedArgument(MGetInlinedArgument* ins) {
|
|||
}
|
||||
|
||||
void LIRGenerator::visitGetArgumentsObjectArg(MGetArgumentsObjectArg* ins) {
|
||||
LAllocation argsObj = useRegister(ins->getArgsObject());
|
||||
LAllocation argsObj = useRegister(ins->argsObject());
|
||||
LGetArgumentsObjectArg* lir =
|
||||
new (alloc()) LGetArgumentsObjectArg(argsObj, temp());
|
||||
defineBox(lir, ins);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitSetArgumentsObjectArg(MSetArgumentsObjectArg* ins) {
|
||||
LAllocation argsObj = useRegister(ins->getArgsObject());
|
||||
LAllocation argsObj = useRegister(ins->argsObject());
|
||||
LSetArgumentsObjectArg* lir = new (alloc())
|
||||
LSetArgumentsObjectArg(argsObj, useBox(ins->getValue()), temp());
|
||||
LSetArgumentsObjectArg(argsObj, useBox(ins->value()), temp());
|
||||
add(lir, ins);
|
||||
}
|
||||
|
||||
|
@ -380,7 +380,7 @@ void LIRGenerator::visitArgumentsObjectLength(MArgumentsObjectLength* ins) {
|
|||
|
||||
void LIRGenerator::visitGuardArgumentsObjectFlags(
|
||||
MGuardArgumentsObjectFlags* ins) {
|
||||
MDefinition* argsObj = ins->getArgsObject();
|
||||
MDefinition* argsObj = ins->argsObject();
|
||||
MOZ_ASSERT(argsObj->type() == MIRType::Object);
|
||||
|
||||
auto* lir =
|
||||
|
|
|
@ -634,6 +634,14 @@ AliasSet MThrow::getAliasSet() const {
|
|||
return AliasSet::Store(AliasSet::ExceptionState);
|
||||
}
|
||||
|
||||
AliasSet MNewArrayDynamicLength::getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::ExceptionState);
|
||||
}
|
||||
|
||||
AliasSet MNewTypedArrayDynamicLength::getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::ExceptionState);
|
||||
}
|
||||
|
||||
#ifdef JS_JITSPEW
|
||||
void MDefinition::printOpcode(GenericPrinter& out) const {
|
||||
PrintOpcodeName(out, op());
|
||||
|
@ -3114,6 +3122,19 @@ AliasSet MArgumentsObjectLength::getAliasSet() const {
|
|||
AliasSet::DynamicSlot);
|
||||
}
|
||||
|
||||
bool MGuardArgumentsObjectFlags::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isGuardArgumentsObjectFlags() ||
|
||||
ins->toGuardArgumentsObjectFlags()->flags() != flags()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MGuardArgumentsObjectFlags::getAliasSet() const {
|
||||
// The flags are packed with the length in a fixed private slot.
|
||||
return AliasSet::Load(AliasSet::FixedSlot);
|
||||
}
|
||||
|
||||
MDefinition* MReturnFromCtor::foldsTo(TempAllocator& alloc) {
|
||||
MDefinition* rval = value();
|
||||
if (rval->isBox()) {
|
||||
|
@ -4108,6 +4129,24 @@ AliasSet MCreateThis::getAliasSet() const {
|
|||
return AliasSet::Load(AliasSet::Any);
|
||||
}
|
||||
|
||||
bool MGetArgumentsObjectArg::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isGetArgumentsObjectArg()) {
|
||||
return false;
|
||||
}
|
||||
if (ins->toGetArgumentsObjectArg()->argno() != argno()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MGetArgumentsObjectArg::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::Any);
|
||||
}
|
||||
|
||||
AliasSet MSetArgumentsObjectArg::getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::Any);
|
||||
}
|
||||
|
||||
MObjectState::MObjectState(MObjectState* state)
|
||||
: MVariadicInstruction(classOpcode),
|
||||
numSlots_(state->numSlots_),
|
||||
|
@ -5098,6 +5137,10 @@ MDefinition* MGetFirstDollarIndex::foldsTo(TempAllocator& alloc) {
|
|||
return MConstant::New(alloc, Int32Value(index));
|
||||
}
|
||||
|
||||
AliasSet MThrowRuntimeLexicalError::getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::ExceptionState);
|
||||
}
|
||||
|
||||
AliasSet MSlots::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
@ -5408,6 +5451,20 @@ bool MCallBindVar::congruentTo(const MDefinition* ins) const {
|
|||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
bool MGuardShape::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isGuardShape()) {
|
||||
return false;
|
||||
}
|
||||
if (shape() != ins->toGuardShape()->shape()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MGuardShape::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
MDefinition* MGuardIsNotProxy::foldsTo(TempAllocator& alloc) {
|
||||
KnownClass known = GetObjectKnownClass(object());
|
||||
if (known == KnownClass::None) {
|
||||
|
@ -5424,10 +5481,107 @@ AliasSet MMegamorphicLoadSlotByValue::getAliasSet() const {
|
|||
AliasSet::DynamicSlot);
|
||||
}
|
||||
|
||||
bool MMegamorphicLoadSlot::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isMegamorphicLoadSlot()) {
|
||||
return false;
|
||||
}
|
||||
if (ins->toMegamorphicLoadSlot()->name() != name()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MMegamorphicLoadSlot::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields | AliasSet::FixedSlot |
|
||||
AliasSet::DynamicSlot);
|
||||
}
|
||||
|
||||
bool MMegamorphicStoreSlot::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isMegamorphicStoreSlot()) {
|
||||
return false;
|
||||
}
|
||||
if (ins->toMegamorphicStoreSlot()->name() != name()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MMegamorphicStoreSlot::getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::ObjectFields | AliasSet::FixedSlot |
|
||||
AliasSet::DynamicSlot);
|
||||
}
|
||||
|
||||
bool MMegamorphicHasProp::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isMegamorphicHasProp()) {
|
||||
return false;
|
||||
}
|
||||
if (ins->toMegamorphicHasProp()->hasOwn() != hasOwn()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MMegamorphicHasProp::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields | AliasSet::FixedSlot |
|
||||
AliasSet::DynamicSlot);
|
||||
}
|
||||
|
||||
bool MNurseryObject::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isNurseryObject()) {
|
||||
return false;
|
||||
}
|
||||
return nurseryIndex() == ins->toNurseryObject()->nurseryIndex();
|
||||
}
|
||||
|
||||
AliasSet MGuardFunctionIsNonBuiltinCtor::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
bool MGuardFunctionKind::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isGuardFunctionKind()) {
|
||||
return false;
|
||||
}
|
||||
if (expected() != ins->toGuardFunctionKind()->expected()) {
|
||||
return false;
|
||||
}
|
||||
if (bailOnEquality() != ins->toGuardFunctionKind()->bailOnEquality()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MGuardFunctionKind::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
bool MGuardFunctionScript::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isGuardFunctionScript()) {
|
||||
return false;
|
||||
}
|
||||
if (expected() != ins->toGuardFunctionScript()->expected()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MGuardFunctionScript::getAliasSet() const {
|
||||
// A JSFunction's BaseScript pointer is immutable. Relazification of
|
||||
// self-hosted functions is an exception to this, but we don't use this
|
||||
// guard for self-hosted functions.
|
||||
MOZ_ASSERT(!flags_.isSelfHostedOrIntrinsic());
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
bool MGuardSpecificAtom::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isGuardSpecificAtom()) {
|
||||
return false;
|
||||
}
|
||||
if (atom() != ins->toGuardSpecificAtom()->atom()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
MDefinition* MGuardStringToIndex::foldsTo(TempAllocator& alloc) {
|
||||
if (!string()->isConstant()) {
|
||||
return this;
|
||||
|
@ -5480,6 +5634,15 @@ AliasSet MGuardNoDenseElements::getAliasSet() const {
|
|||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
AliasSet MCopyLexicalEnvironmentObject::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields | AliasSet::FixedSlot |
|
||||
AliasSet::DynamicSlot);
|
||||
}
|
||||
|
||||
AliasSet MAllocateAndStoreSlot::getAliasSet() const {
|
||||
return AliasSet::Store(AliasSet::ObjectFields | AliasSet::DynamicSlot);
|
||||
}
|
||||
|
||||
AliasSet MLoadDOMExpandoValue::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::DOMProxyExpando);
|
||||
}
|
||||
|
@ -5488,6 +5651,21 @@ AliasSet MLoadDOMExpandoValueIgnoreGeneration::getAliasSet() const {
|
|||
return AliasSet::Load(AliasSet::DOMProxyExpando);
|
||||
}
|
||||
|
||||
bool MGuardDOMExpandoMissingOrGuardShape::congruentTo(
|
||||
const MDefinition* ins) const {
|
||||
if (!ins->isGuardDOMExpandoMissingOrGuardShape()) {
|
||||
return false;
|
||||
}
|
||||
if (shape() != ins->toGuardDOMExpandoMissingOrGuardShape()->shape()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MGuardDOMExpandoMissingOrGuardShape::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
MDefinition* MGuardToClass::foldsTo(TempAllocator& alloc) {
|
||||
const JSClass* clasp = GetObjectKnownJSClass(object());
|
||||
if (!clasp || getClass() != clasp) {
|
||||
|
@ -5640,6 +5818,23 @@ AliasSet MLoadWrapperTarget::getAliasSet() const {
|
|||
return AliasSet::Load(AliasSet::Any);
|
||||
}
|
||||
|
||||
AliasSet MGuardHasGetterSetter::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
||||
bool MGuardHasGetterSetter::congruentTo(const MDefinition* ins) const {
|
||||
if (!ins->isGuardHasGetterSetter()) {
|
||||
return false;
|
||||
}
|
||||
if (ins->toGuardHasGetterSetter()->propId() != propId()) {
|
||||
return false;
|
||||
}
|
||||
if (ins->toGuardHasGetterSetter()->getterSetter() != getterSetter()) {
|
||||
return false;
|
||||
}
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
AliasSet MGuardIsExtensible::getAliasSet() const {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
|
@ -5754,3 +5949,18 @@ MDefinition* MGetInlinedArgument::foldsTo(TempAllocator& alloc) {
|
|||
|
||||
return arg;
|
||||
}
|
||||
|
||||
bool MWasmShiftSimd128::congruentTo(const MDefinition* ins) const {
|
||||
return ins->toWasmShiftSimd128()->simdOp() == simdOp_ &&
|
||||
congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
bool MWasmShuffleSimd128::congruentTo(const MDefinition* ins) const {
|
||||
return ins->toWasmShuffleSimd128()->control().bitwiseEqual(control_) &&
|
||||
congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
bool MWasmUnarySimd128::congruentTo(const MDefinition* ins) const {
|
||||
return ins->toWasmUnarySimd128()->simdOp() == simdOp_ &&
|
||||
congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
|
1148
js/src/jit/MIR.h
1148
js/src/jit/MIR.h
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -26,8 +26,8 @@
|
|||
#
|
||||
# operands
|
||||
# ========
|
||||
# A list of operands for the MIR op class constructor.
|
||||
# The operand kind is specified from the one of the kinds from
|
||||
# A list of operands for the MIR op class constructor. Each operand is a
|
||||
# MIR node. The operand kind is specified from the one of the kinds from
|
||||
# the MIRType enum in IonTypes.h. The specified types for the
|
||||
# operands will decide the type policy for the instruction.
|
||||
#
|
||||
|
@ -47,6 +47,31 @@
|
|||
# - attribute not specified (default): no code generated
|
||||
# - operand list: MIRTypes (See MIRType in jit/IonTypes.h)
|
||||
#
|
||||
# arguments
|
||||
# =========
|
||||
# A list of non-MIR node arguments to the MIR op class constructor
|
||||
# that are passed along with the operands. The arguments require
|
||||
# both a name and a full type signature for each item in the list.
|
||||
#
|
||||
# For example:
|
||||
# templateObject: JSObject*
|
||||
# initialHeap: gc::InitialHeap
|
||||
#
|
||||
# For each argument a private variable declaration will be autogenerated
|
||||
# in the MIR op class, as well as simple accessor for that variable. If
|
||||
# the type of the variable is a GC pointer it will by automatically
|
||||
# wrapped by CompilerGCPointer. The above arguments list will result in
|
||||
# the following declarations and accessors:
|
||||
#
|
||||
# CompilerGCPointer<JSObject*> templateObject_;
|
||||
# gc::InitialHeap initialHeap_;
|
||||
#
|
||||
# JSObject* templateObject() const { return templateObject_; }
|
||||
# gc::InitialHeap initialHeap() const { return initialHeap_; }
|
||||
#
|
||||
# - attribute not specified (default): no code generated
|
||||
# - operand list: argument names and their full type signature
|
||||
#
|
||||
# type_policy
|
||||
# ============
|
||||
# If this attribute is present, then the type policy for that opcode will be
|
||||
|
@ -194,19 +219,54 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: NewArrayDynamicLength
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
length: Int32
|
||||
arguments:
|
||||
templateObject: JSObject*
|
||||
initialHeap: gc::InitialHeap
|
||||
result_type: Object
|
||||
# Need to throw if length is negative.
|
||||
guard: true
|
||||
# Throws if length is negative.
|
||||
alias_set: custom
|
||||
|
||||
- name: NewTypedArray
|
||||
gen_boilerplate: false
|
||||
|
||||
- name: NewTypedArrayDynamicLength
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
length: Int32
|
||||
arguments:
|
||||
templateObject: JSObject*
|
||||
initialHeap: gc::InitialHeap
|
||||
result_type: Object
|
||||
guard: true
|
||||
# Throws if length is negative.
|
||||
alias_set: custom
|
||||
|
||||
# Create a new TypedArray from an Array (or Array-like object) or a TypedArray.
|
||||
- name: NewTypedArrayFromArray
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
array: Object
|
||||
arguments:
|
||||
templateObject: JSObject*
|
||||
initialHeap: gc::InitialHeap
|
||||
result_type: Object
|
||||
guard: true
|
||||
possibly_calls: true
|
||||
|
||||
# Create a new TypedArray from an ArrayBuffer (or SharedArrayBuffer).
|
||||
- name: NewTypedArrayFromArrayBuffer
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
arrayBuffer: Object
|
||||
byteOffset: Value
|
||||
length: Value
|
||||
arguments:
|
||||
templateObject: JSObject*
|
||||
initialHeap: gc::InitialHeap
|
||||
result_type: Object
|
||||
guard: true
|
||||
possibly_calls: true
|
||||
|
||||
- name: NewObject
|
||||
gen_boilerplate: false
|
||||
|
@ -235,7 +295,11 @@
|
|||
possibly_calls: true
|
||||
|
||||
- name: InitPropGetterSetter
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
value: Object
|
||||
arguments:
|
||||
name: PropertyName*
|
||||
|
||||
- name: InitElemGetterSetter
|
||||
operands:
|
||||
|
@ -339,10 +403,21 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: GetArgumentsObjectArg
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
argsObject: Object
|
||||
arguments:
|
||||
argno: size_t
|
||||
result_type: Value
|
||||
congruent_to: custom
|
||||
alias_set: custom
|
||||
|
||||
- name: SetArgumentsObjectArg
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
argsObject: Object
|
||||
value: Value
|
||||
arguments:
|
||||
argno: size_t
|
||||
alias_set: custom
|
||||
|
||||
# Load |arguments[index]| from a mapped or unmapped arguments object. Bails out
|
||||
# if any elements were overridden or deleted. Also bails out if the index is
|
||||
|
@ -369,8 +444,18 @@
|
|||
# property read.
|
||||
alias_set: custom
|
||||
|
||||
# Guard that the given flags are not set on the arguments object.
|
||||
- name: GuardArgumentsObjectFlags
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
argsObject: Object
|
||||
arguments:
|
||||
flags: uint32_t
|
||||
result_type: Object
|
||||
movable: true
|
||||
guard: true
|
||||
congruent_to: custom
|
||||
# The flags are packed with the length in a fixed private slot.
|
||||
alias_set: custom
|
||||
|
||||
# Given a MIRType::Value A and a MIRType::Object B:
|
||||
# If the Value may be safely unboxed to an Object, return Object(A).
|
||||
|
@ -705,10 +790,24 @@
|
|||
can_recover: true
|
||||
|
||||
- name: BoxNonStrictThis
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
def: Value
|
||||
arguments:
|
||||
globalThis: JSObject*
|
||||
result_type: Object
|
||||
folds_to: custom
|
||||
possibly_calls: true
|
||||
# This instruction can allocate a new object for wrapped primitives, but
|
||||
# has no effect on existing objects.
|
||||
alias_set: none
|
||||
|
||||
- name: ImplicitThis
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
envChain: Object
|
||||
arguments:
|
||||
name: PropertyName*
|
||||
result_type: Value
|
||||
possibly_calls: true
|
||||
|
||||
# Load an arrow function's |new.target| value.
|
||||
- name: ArrowNewTarget
|
||||
|
@ -769,8 +868,13 @@
|
|||
- name: LexicalCheck
|
||||
gen_boilerplate: false
|
||||
|
||||
# Unconditionally throw an uninitialized let error.
|
||||
- name: ThrowRuntimeLexicalError
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
errorNumber: unsigned
|
||||
result_type: None
|
||||
guard: true
|
||||
alias_set: custom
|
||||
|
||||
- name: ThrowMsg
|
||||
gen_boilerplate: false
|
||||
|
@ -781,7 +885,12 @@
|
|||
guard: true
|
||||
|
||||
- name: RegExp
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
source: RegExpObject*
|
||||
hasShared: bool
|
||||
result_type: Object
|
||||
possibly_calls: true
|
||||
alias_set: none
|
||||
|
||||
- name: RegExpMatcher
|
||||
operands:
|
||||
|
@ -839,7 +948,9 @@
|
|||
alias_set: none
|
||||
|
||||
- name: ModuleMetadata
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
module: JSObject*
|
||||
result_type: Object
|
||||
|
||||
- name: DynamicImport
|
||||
operands:
|
||||
|
@ -856,7 +967,13 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: SetFunName
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
fun: Object
|
||||
name: Value
|
||||
arguments:
|
||||
prefixKind: uint8_t
|
||||
result_type: None
|
||||
possibly_calls: true
|
||||
|
||||
# Returns obj->slots.
|
||||
- name: Slots
|
||||
|
@ -898,7 +1015,6 @@
|
|||
alias_set: custom
|
||||
clone: true
|
||||
|
||||
|
||||
# Load the array length from an elements header.
|
||||
- name: ArrayLength
|
||||
operands:
|
||||
|
@ -911,7 +1027,6 @@
|
|||
compute_range: custom
|
||||
clone: true
|
||||
|
||||
|
||||
# Store to the length in an elements header. Note the input is an *index*, one
|
||||
# less than the desired length.
|
||||
- name: SetArrayLength
|
||||
|
@ -1063,8 +1178,17 @@
|
|||
compute_range: custom
|
||||
clone: true
|
||||
|
||||
# Array.prototype.slice on a dense array.
|
||||
- name: ArraySlice
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
begin: Int32
|
||||
end: Int32
|
||||
arguments:
|
||||
templateObj: JSObject*
|
||||
initialHeap: gc::InitialHeap
|
||||
result_type: Object
|
||||
possibly_calls: true
|
||||
|
||||
# MArrayJoin doesn't override |getAliasSet()|, because Array.prototype.join
|
||||
# might coerce the elements of the Array to strings. This coercion might
|
||||
|
@ -1144,7 +1268,16 @@
|
|||
alias_set: none
|
||||
|
||||
- name: GuardShape
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
arguments:
|
||||
shape: Shape*
|
||||
result_type: Object
|
||||
guard: true
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
folds_to: custom
|
||||
alias_set: custom
|
||||
|
||||
- name: GuardProto
|
||||
gen_boilerplate: false
|
||||
|
@ -1191,7 +1324,12 @@
|
|||
alias_set: none
|
||||
|
||||
- name: ProxyGet
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
proxy: Object
|
||||
arguments:
|
||||
id: jsid
|
||||
result_type: Value
|
||||
possibly_calls: true
|
||||
|
||||
- name: ProxyGetByValue
|
||||
operands:
|
||||
|
@ -1201,19 +1339,52 @@
|
|||
possibly_calls: true
|
||||
|
||||
- name: ProxyHasProp
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
proxy: Object
|
||||
idVal: Value
|
||||
arguments:
|
||||
hasOwn: bool
|
||||
result_type: Boolean
|
||||
possibly_calls: true
|
||||
|
||||
- name: ProxySet
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
proxy: Object
|
||||
rhs: Value
|
||||
arguments:
|
||||
id: jsid
|
||||
strict: bool
|
||||
possibly_calls: true
|
||||
|
||||
- name: ProxySetByValue
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
proxy: Object
|
||||
idVal: Value
|
||||
rhs: Value
|
||||
arguments:
|
||||
strict: bool
|
||||
possibly_calls: true
|
||||
|
||||
- name: CallSetArrayLength
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
obj: Object
|
||||
rhs: Value
|
||||
arguments:
|
||||
strict: bool
|
||||
possibly_calls: true
|
||||
|
||||
- name: MegamorphicLoadSlot
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
arguments:
|
||||
name: PropertyName*
|
||||
result_type: Value
|
||||
# Bails when non-native or accessor properties are encountered, so we can't
|
||||
# DCE this instruction.
|
||||
guard: true
|
||||
possibly_calls: true
|
||||
congruent_to: custom
|
||||
alias_set: custom
|
||||
|
||||
- name: MegamorphicLoadSlotByValue
|
||||
operands:
|
||||
|
@ -1228,10 +1399,28 @@
|
|||
possibly_calls: true
|
||||
|
||||
- name: MegamorphicStoreSlot
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
rhs: Value
|
||||
arguments:
|
||||
name: PropertyName*
|
||||
congruent_to: custom
|
||||
alias_set: custom
|
||||
possibly_calls: true
|
||||
|
||||
- name: MegamorphicHasProp
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
idVal: Value
|
||||
arguments:
|
||||
hasOwn: bool
|
||||
result_type: Boolean
|
||||
# Bails when non-native or accessor properties are encountered, so we can't
|
||||
# DCE this instruction.
|
||||
guard: true
|
||||
congruent_to: custom
|
||||
alias_set: custom
|
||||
possibly_calls: true
|
||||
|
||||
- name: GuardIsNotArrayBufferMaybeShared
|
||||
operands:
|
||||
|
@ -1252,8 +1441,16 @@
|
|||
congruent_to: if_operands_equal
|
||||
alias_set: none
|
||||
|
||||
# Loads a specific JSObject* that was originally nursery-allocated.
|
||||
# See also WarpObjectField.
|
||||
- name: NurseryObject
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
# Index in the Vector of objects stored in the WarpSnapshot.
|
||||
nurseryIndex: uint32_t
|
||||
result_type: Object
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
alias_set: none
|
||||
|
||||
- name: GuardValue
|
||||
gen_boilerplate: false
|
||||
|
@ -1281,10 +1478,33 @@
|
|||
alias_set: custom
|
||||
|
||||
- name: GuardFunctionKind
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
function: Object
|
||||
arguments:
|
||||
expected: FunctionFlags::FunctionKind
|
||||
bailOnEquality: bool
|
||||
result_type: Object
|
||||
guard: true
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
alias_set: custom
|
||||
|
||||
- name: GuardFunctionScript
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
function: Object
|
||||
arguments:
|
||||
expected: BaseScript*
|
||||
nargs: uint16_t
|
||||
flags: FunctionFlags
|
||||
result_type: Object
|
||||
guard: true
|
||||
movable: true
|
||||
folds_to: custom
|
||||
congruent_to: custom
|
||||
# A JSFunction's BaseScript pointer is immutable. Relazification of
|
||||
# self-hosted functions is an exception to this, but we don't use this
|
||||
# guard for self-hosted functions.
|
||||
alias_set: custom
|
||||
|
||||
- name: GuardObjectIdentity
|
||||
gen_boilerplate: false
|
||||
|
@ -1293,7 +1513,16 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: GuardSpecificAtom
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
str: String
|
||||
arguments:
|
||||
atom: JSAtom*
|
||||
result_type: String
|
||||
guard: true
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
folds_to: custom
|
||||
alias_set: none
|
||||
|
||||
- name: GuardSpecificSymbol
|
||||
gen_boilerplate: false
|
||||
|
@ -1362,11 +1591,25 @@
|
|||
- name: NewLexicalEnvironmentObject
|
||||
gen_boilerplate: false
|
||||
|
||||
# Allocate a new ClassBodyEnvironmentObject.
|
||||
- name: NewClassBodyEnvironmentObject
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
enclosing: Object
|
||||
arguments:
|
||||
scope: ClassBodyScope*
|
||||
result_type: Object
|
||||
possibly_calls: true
|
||||
alias_set: none
|
||||
|
||||
# Allocate a new BlockLexicalEnvironmentObject from an existing one.
|
||||
- name: CopyLexicalEnvironmentObject
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
env: Object
|
||||
arguments:
|
||||
copySlots: bool
|
||||
result_type: Object
|
||||
possibly_calls: true
|
||||
alias_set: custom
|
||||
|
||||
- name: HomeObject
|
||||
operands:
|
||||
|
@ -1380,7 +1623,15 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: AllocateAndStoreSlot
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
value: Value
|
||||
arguments:
|
||||
slotOffset: uint32_t
|
||||
shape: Shape*
|
||||
numNewSlots: uint32_t
|
||||
possibly_calls: true
|
||||
alias_set: custom
|
||||
|
||||
- name: StoreDynamicSlot
|
||||
gen_boilerplate: false
|
||||
|
@ -1391,13 +1642,27 @@
|
|||
result_type: Value
|
||||
|
||||
- name: CallGetIntrinsicValue
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
name: PropertyName*
|
||||
result_type: Value
|
||||
possibly_calls: true
|
||||
alias_set: none
|
||||
|
||||
- name: DeleteProperty
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
value: Value
|
||||
arguments:
|
||||
name: PropertyName*
|
||||
strict: bool
|
||||
result_type: Boolean
|
||||
|
||||
- name: DeleteElement
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
value: Value
|
||||
index: Value
|
||||
arguments:
|
||||
strict: bool
|
||||
result_type: Boolean
|
||||
|
||||
- name: SetPropertyCache
|
||||
gen_boilerplate: false
|
||||
|
@ -1437,8 +1702,18 @@
|
|||
congruent_to: if_operands_equal
|
||||
alias_set: custom
|
||||
|
||||
# Takes an expando Value as input, then guards it's either UndefinedValue or
|
||||
# an object with the expected shape.
|
||||
- name: GuardDOMExpandoMissingOrGuardShape
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
expando: Value
|
||||
arguments:
|
||||
shape: Shape*
|
||||
result_type: Value
|
||||
guard: true
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
alias_set: custom
|
||||
|
||||
- name: StringLength
|
||||
operands:
|
||||
|
@ -1546,7 +1821,14 @@
|
|||
alias_set: none
|
||||
|
||||
- name: Rest
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
numActuals: Int32
|
||||
arguments:
|
||||
numFormals: unsigned
|
||||
shape: Shape*
|
||||
result_type: Object
|
||||
possibly_calls: true
|
||||
alias_set: none
|
||||
|
||||
- name: PostWriteBarrier
|
||||
gen_boilerplate: false
|
||||
|
@ -1555,7 +1837,10 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: NewNamedLambdaObject
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
templateObj: NamedLambdaObject*
|
||||
result_type: Object
|
||||
alias_set: none
|
||||
|
||||
- name: NewCallObject
|
||||
gen_boilerplate: false
|
||||
|
@ -1641,7 +1926,12 @@
|
|||
alias_set: none
|
||||
|
||||
- name: AsyncResolve
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
generator: Object
|
||||
valueOrReason: Value
|
||||
arguments:
|
||||
resolveKind: AsyncFunctionResolveKind
|
||||
result_type: Object
|
||||
|
||||
# Returns from this function to the previous caller; this looks like a regular
|
||||
# Unary instruction and is used to lie to the MIR generator about suspending
|
||||
|
@ -1679,7 +1969,9 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: IncrementWarmUpCounter
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
script: JSScript*
|
||||
alias_set: none
|
||||
|
||||
- name: AtomicIsLockFree
|
||||
gen_boilerplate: false
|
||||
|
@ -1697,7 +1989,14 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: CheckIsObj
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
value: Value
|
||||
arguments:
|
||||
checkKind: uint8_t
|
||||
result_type: Object
|
||||
guard: true
|
||||
folds_to: custom
|
||||
alias_set: none
|
||||
|
||||
- name: CheckObjCoercible
|
||||
operands:
|
||||
|
@ -1761,7 +2060,10 @@
|
|||
gen_boilerplate: false
|
||||
|
||||
- name: BuiltinObject
|
||||
gen_boilerplate: false
|
||||
arguments:
|
||||
builtinObjectKind: BuiltinObjectKind
|
||||
result_type: Object
|
||||
possibly_calls: true
|
||||
|
||||
- name: SuperFunction
|
||||
operands:
|
||||
|
@ -1809,8 +2111,19 @@
|
|||
# TODO: Investigate using a narrower or a custom alias set.
|
||||
alias_set: custom
|
||||
|
||||
# Guard the accessor shape is present on the object or its prototype chain.
|
||||
- name: GuardHasGetterSetter
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
arguments:
|
||||
propId: jsid
|
||||
getterSetter: GetterSetter*
|
||||
result_type: Object
|
||||
guard: true
|
||||
movable: true
|
||||
possibly_calls: true
|
||||
congruent_to: custom
|
||||
alias_set: custom
|
||||
|
||||
- name: GuardIsExtensible
|
||||
operands:
|
||||
|
@ -1855,8 +2168,17 @@
|
|||
congruent_to: if_operands_equal
|
||||
alias_set: custom
|
||||
|
||||
# Add or update a sparse element of an array object. It's allowed for the
|
||||
# sparse element to be already present on the array. It may also be an accessor
|
||||
# property, so this instruction is always marked as effectful.
|
||||
- name: CallAddOrUpdateSparseElement
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
object: Object
|
||||
index: Int32
|
||||
value: Value
|
||||
arguments:
|
||||
strict: bool
|
||||
possibly_calls: true
|
||||
|
||||
# Get a sparse element from an array object, possibly by calling an accessor
|
||||
# property.
|
||||
|
@ -2036,17 +2358,48 @@
|
|||
- name: WasmBinarySimd128WithConstant
|
||||
gen_boilerplate: false
|
||||
|
||||
# (v128, i32) -> v128 effect-free shift operations.
|
||||
- name: WasmShiftSimd128
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
lhs: Simd128
|
||||
rhs: Int32
|
||||
arguments:
|
||||
simdOp: wasm::SimdOp
|
||||
type_policy: none
|
||||
result_type: Simd128
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
alias_set: none
|
||||
clone: true
|
||||
|
||||
# (v128, v128, mask) -> v128 effect-free operation.
|
||||
- name: WasmShuffleSimd128
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
lhs: Simd128
|
||||
rhs: Simd128
|
||||
arguments:
|
||||
control: SimdConstant
|
||||
type_policy: none
|
||||
result_type: Simd128
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
alias_set: none
|
||||
clone: true
|
||||
|
||||
- name: WasmReplaceLaneSimd128
|
||||
gen_boilerplate: false
|
||||
|
||||
- name: WasmUnarySimd128
|
||||
gen_boilerplate: false
|
||||
operands:
|
||||
src: Simd128
|
||||
arguments:
|
||||
simdOp: wasm::SimdOp
|
||||
type_policy: none
|
||||
result_type: Simd128
|
||||
movable: true
|
||||
congruent_to: custom
|
||||
alias_set: none
|
||||
clone: true
|
||||
|
||||
- name: WasmScalarToSimd128
|
||||
gen_boilerplate: false
|
||||
|
|
|
@ -1559,7 +1559,7 @@ void ArgumentsReplacer::visitGuardToClass(MGuardToClass* ins) {
|
|||
void ArgumentsReplacer::visitGuardArgumentsObjectFlags(
|
||||
MGuardArgumentsObjectFlags* ins) {
|
||||
// Skip other arguments objects.
|
||||
if (ins->getArgsObject() != args_) {
|
||||
if (ins->argsObject() != args_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1610,7 +1610,7 @@ void ArgumentsReplacer::visitUnbox(MUnbox* ins) {
|
|||
void ArgumentsReplacer::visitGetArgumentsObjectArg(
|
||||
MGetArgumentsObjectArg* ins) {
|
||||
// Skip other arguments objects.
|
||||
if (ins->getArgsObject() != args_) {
|
||||
if (ins->argsObject() != args_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -966,7 +966,7 @@ bool WarpBuilder::build_SetArg(BytecodeLocation loc) {
|
|||
// must go through the arguments object.
|
||||
MDefinition* argsObj = current->argumentsObject();
|
||||
current->add(MPostWriteBarrier::New(alloc(), argsObj, val));
|
||||
auto* ins = MSetArgumentsObjectArg::New(alloc(), argsObj, arg, val);
|
||||
auto* ins = MSetArgumentsObjectArg::New(alloc(), argsObj, val, arg);
|
||||
current->add(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
|
@ -2525,7 +2525,7 @@ bool WarpBuilder::buildInitPropGetterSetterOp(BytecodeLocation loc) {
|
|||
MDefinition* value = current->pop();
|
||||
MDefinition* obj = current->peek(-1);
|
||||
|
||||
auto* ins = MInitPropGetterSetter::New(alloc(), obj, name, value);
|
||||
auto* ins = MInitPropGetterSetter::New(alloc(), obj, value, name);
|
||||
current->add(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ bool WarpCacheIRTranspiler::emitProxySet(ObjOperandId objId, uint32_t idOffset,
|
|||
jsid id = idStubField(idOffset);
|
||||
MDefinition* rhs = getOperand(rhsId);
|
||||
|
||||
auto* ins = MProxySet::New(alloc(), obj, id, rhs, strict);
|
||||
auto* ins = MProxySet::New(alloc(), obj, rhs, id, strict);
|
||||
addEffectful(ins);
|
||||
|
||||
return resumeAfter(ins);
|
||||
|
@ -663,7 +663,7 @@ bool WarpCacheIRTranspiler::emitMegamorphicStoreSlot(ObjOperandId objId,
|
|||
PropertyName* name = stringStubField(nameOffset)->asAtom().asPropertyName();
|
||||
MDefinition* rhs = getOperand(rhsId);
|
||||
|
||||
auto* ins = MMegamorphicStoreSlot::New(alloc(), obj, name, rhs);
|
||||
auto* ins = MMegamorphicStoreSlot::New(alloc(), obj, rhs, name);
|
||||
addEffectful(ins);
|
||||
|
||||
return resumeAfter(ins);
|
||||
|
@ -3577,7 +3577,7 @@ bool WarpCacheIRTranspiler::emitNewArrayFromLengthResult(
|
|||
}
|
||||
}
|
||||
|
||||
auto* obj = MNewArrayDynamicLength::New(alloc(), templateObj, heap, length);
|
||||
auto* obj = MNewArrayDynamicLength::New(alloc(), length, templateObj, heap);
|
||||
addEffectful(obj);
|
||||
pushResult(obj);
|
||||
return resumeAfter(obj);
|
||||
|
@ -3604,7 +3604,7 @@ bool WarpCacheIRTranspiler::emitNewTypedArrayFromLengthResult(
|
|||
}
|
||||
|
||||
auto* obj =
|
||||
MNewTypedArrayDynamicLength::New(alloc(), templateObj, heap, length);
|
||||
MNewTypedArrayDynamicLength::New(alloc(), length, templateObj, heap);
|
||||
addEffectful(obj);
|
||||
pushResult(obj);
|
||||
return resumeAfter(obj);
|
||||
|
@ -3621,8 +3621,8 @@ bool WarpCacheIRTranspiler::emitNewTypedArrayFromArrayBufferResult(
|
|||
// TODO: support pre-tenuring.
|
||||
gc::InitialHeap heap = gc::DefaultHeap;
|
||||
|
||||
auto* obj = MNewTypedArrayFromArrayBuffer::New(alloc(), templateObj, heap,
|
||||
buffer, byteOffset, length);
|
||||
auto* obj = MNewTypedArrayFromArrayBuffer::New(alloc(), buffer, byteOffset,
|
||||
length, templateObj, heap);
|
||||
addEffectful(obj);
|
||||
|
||||
pushResult(obj);
|
||||
|
@ -3637,7 +3637,7 @@ bool WarpCacheIRTranspiler::emitNewTypedArrayFromArrayResult(
|
|||
// TODO: support pre-tenuring.
|
||||
gc::InitialHeap heap = gc::DefaultHeap;
|
||||
|
||||
auto* obj = MNewTypedArrayFromArray::New(alloc(), templateObj, heap, array);
|
||||
auto* obj = MNewTypedArrayFromArray::New(alloc(), array, templateObj, heap);
|
||||
addEffectful(obj);
|
||||
|
||||
pushResult(obj);
|
||||
|
|
Загрузка…
Ссылка в новой задаче