bool RNewDerivedTypedObject::recover(JSContext* cx, SnapshotIterator& iter) const { Rooted<TypeDescr*> descr(cx, &iter.read().toObject().as<TypeDescr>()); Rooted<TypedObject*> owner(cx, &iter.read().toObject().as<TypedObject>()); int32_t offset = iter.read().toInt32(); JSObject* obj = OutlineTypedObject::createDerived(cx, descr, owner, offset); if (!obj) return false; RootedValue result(cx, ObjectValue(*obj)); iter.storeInstructionResult(result); return true; }
bool RRegExpTest::recover(JSContext *cx, SnapshotIterator &iter) const { RootedString string(cx, iter.read().toString()); RootedObject regexp(cx, &iter.read().toObject()); bool resultBool; if (!js::regexp_test_raw(cx, regexp, string, &resultBool)) return false; RootedValue result(cx); result.setBoolean(resultBool); iter.storeInstructionResult(result); return true; }
bool RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const { RootedObject templateObject(cx, &iter.read().toObject()); RootedValue result(cx); RootedObjectGroup group(cx, templateObject->group()); JSObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_); if (!resultObject) return false; result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RPowHalf::recover(JSContext *cx, SnapshotIterator &iter) const { RootedValue base(cx, iter.read()); RootedValue power(cx); RootedValue result(cx); power.setNumber(0.5); MOZ_ASSERT(base.isNumber()); if (!js::math_pow_handle(cx, base, power, &result)) return false; iter.storeInstructionResult(result); return true; }
bool RRsh::recover(JSContext *cx, SnapshotIterator &iter) const { RootedValue lhs(cx, iter.read()); RootedValue rhs(cx, iter.read()); MOZ_ASSERT(!lhs.isObject() && !rhs.isObject()); int32_t result; if (!js::BitRsh(cx, lhs, rhs, &result)) return false; RootedValue rootedResult(cx, js::Int32Value(result)); iter.storeInstructionResult(rootedResult); return true; }
bool RLambda::recover(JSContext* cx, SnapshotIterator& iter) const { RootedObject scopeChain(cx, &iter.read().toObject()); RootedFunction fun(cx, &iter.read().toObject().as<JSFunction>()); JSObject* resultObject = js::Lambda(cx, fun, scopeChain); if (!resultObject) return false; RootedValue result(cx); result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RCreateThisWithTemplate::recover(JSContext* cx, SnapshotIterator& iter) const { RootedObject templateObject(cx, &iter.read().toObject()); // See CodeGenerator::visitCreateThisWithTemplate JSObject* resultObject = NewObjectOperationWithTemplate(cx, templateObject); if (!resultObject) return false; RootedValue result(cx); result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RStringReplace::recover(JSContext* cx, SnapshotIterator& iter) const { RootedString string(cx, iter.read().toString()); RootedString pattern(cx, iter.read().toString()); RootedString replace(cx, iter.read().toString()); JSString* result = isFlatReplacement_ ? js::str_flat_replace_string(cx, string, pattern, replace) : js::str_replace_string_raw(cx, string, pattern, replace); if (!result) return false; iter.storeInstructionResult(StringValue(result)); return true; }
bool RStringSplit::recover(JSContext *cx, SnapshotIterator &iter) const { RootedString str(cx, iter.read().toString()); RootedString sep(cx, iter.read().toString()); RootedTypeObject typeObj(cx, iter.read().toObject().type()); RootedValue result(cx); JSObject *res = str_split_string(cx, typeObj, str, sep); if (!res) return false; result.setObject(*res); iter.storeInstructionResult(result); return true; }
bool RRegExpTester::recover(JSContext* cx, SnapshotIterator& iter) const { RootedString string(cx, iter.read().toString()); RootedObject regexp(cx, &iter.read().toObject()); int32_t lastIndex = iter.read().toInt32(); int32_t endIndex; if (!js::RegExpTesterRaw(cx, regexp, string, lastIndex, &endIndex)) return false; RootedValue result(cx); result.setInt32(endIndex); iter.storeInstructionResult(result); return true; }
bool RRegExpSearcher::recover(JSContext* cx, SnapshotIterator& iter) const { RootedObject regexp(cx, &iter.read().toObject()); RootedString input(cx, iter.read().toString()); int32_t lastIndex = iter.read().toInt32(); int32_t result; if (!RegExpSearcherRaw(cx, regexp, input, lastIndex, nullptr, &result)) return false; RootedValue resultVal(cx); resultVal.setInt32(result); iter.storeInstructionResult(resultVal); return true; }
bool RObjectState::recover(JSContext *cx, SnapshotIterator &iter) const { RootedNativeObject object(cx, &iter.read().toObject().as<NativeObject>()); MOZ_ASSERT(object->slotSpan() == numSlots()); RootedValue val(cx); for (size_t i = 0; i < numSlots(); i++) { val = iter.read(); object->setSlot(i, val); } val.setObject(*object); iter.storeInstructionResult(val); return true; }
bool RToDouble::recover(JSContext* cx, SnapshotIterator& iter) const { RootedValue v(cx, iter.read()); RootedValue result(cx); MOZ_ASSERT(!v.isObject()); MOZ_ASSERT(!v.isSymbol()); double dbl; if (!ToNumber(cx, v, &dbl)) return false; result.setDouble(dbl); iter.storeInstructionResult(result); return true; }
bool RCreateThisWithTemplate::recover(JSContext *cx, SnapshotIterator &iter) const { RootedNativeObject templateObject(cx, &iter.read().toObject().as<NativeObject>()); // See CodeGenerator::visitCreateThisWithTemplate gc::AllocKind allocKind = templateObject->asTenured().getAllocKind(); gc::InitialHeap initialHeap = tenuredHeap_ ? gc::TenuredHeap : gc::DefaultHeap; JSObject *resultObject = NativeObject::copy(cx, allocKind, initialHeap, templateObject); if (!resultObject) return false; RootedValue result(cx); result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RSqrt::recover(JSContext *cx, SnapshotIterator &iter) const { RootedValue num(cx, iter.read()); RootedValue result(cx); MOZ_ASSERT(num.isNumber()); if (!math_sqrt_handle(cx, num, &result)) return false; // MIRType_Float32 is a specialization embedding the fact that the result is // rounded to a Float32. if (isFloatOperation_ && !RoundFloat32(cx, result, &result)) return false; iter.storeInstructionResult(result); return true; }
bool RDiv::recover(JSContext *cx, SnapshotIterator &iter) const { RootedValue lhs(cx, iter.read()); RootedValue rhs(cx, iter.read()); RootedValue result(cx); if (!js::DivValues(cx, &lhs, &rhs, &result)) return false; // MIRType_Float32 is a specialization embedding the fact that the result is // rounded to a Float32. if (isFloatOperation_ && !RoundFloat32(cx, result, &result)) return false; iter.storeInstructionResult(result); return true; }
bool RNewArray::recover(JSContext *cx, SnapshotIterator &iter) const { RootedObject templateObject(cx, &iter.read().toObject()); RootedValue result(cx); RootedTypeObject type(cx); // See CodeGenerator::visitNewArrayCallVM if (!templateObject->hasSingletonType()) type = templateObject->type(); JSObject *resultObject = NewDenseArray(cx, count_, type, allocatingBehaviour_); if (!resultObject) return false; result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RHypot::recover(JSContext* cx, SnapshotIterator& iter) const { JS::AutoValueVector vec(cx); if (!vec.reserve(numOperands_)) return false; for (uint32_t i = 0 ; i < numOperands_ ; ++i) vec.infallibleAppend(iter.read()); RootedValue result(cx); if(!js::math_hypot_handle(cx, vec, &result)) return false; iter.storeInstructionResult(result); return true; }
bool RNewDerivedTypedObject::recover(JSContext *cx, SnapshotIterator &iter) const { Rooted<SizedTypeDescr *> descr(cx, &iter.read().toObject().as<SizedTypeDescr>()); Rooted<TypedObject *> owner(cx, &iter.read().toObject().as<TypedObject>()); int32_t offset = iter.read().toInt32(); // Use AutoEnterAnalysis to avoid invoking the object metadata callback // while bailing out, which could try to walk the stack. types::AutoEnterAnalysis enter(cx); JSObject *obj = TypedObject::createDerived(cx, descr, owner, offset); if (!obj) return false; RootedValue result(cx, ObjectValue(*obj)); iter.storeInstructionResult(result); return true; }
bool RObjectState::recover(JSContext* cx, SnapshotIterator& iter) const { RootedObject object(cx, &iter.read().toObject()); RootedValue val(cx); if (object->is<UnboxedPlainObject>()) { const UnboxedLayout& layout = object->as<UnboxedPlainObject>().layout(); RootedId id(cx); RootedValue receiver(cx, ObjectValue(*object)); const UnboxedLayout::PropertyVector& properties = layout.properties(); for (size_t i = 0; i < properties.length(); i++) { val = iter.read(); // This is the default placeholder value of MObjectState, when no // properties are defined yet. if (val.isUndefined()) continue; id = NameToId(properties[i].name); ObjectOpResult result; // SetProperty can only fail due to OOM. if (!SetProperty(cx, object, id, val, receiver, result)) return false; if (!result) return result.reportError(cx, object, id); } } else { RootedNativeObject nativeObject(cx, &object->as<NativeObject>()); MOZ_ASSERT(nativeObject->slotSpan() == numSlots()); for (size_t i = 0; i < numSlots(); i++) { val = iter.read(); nativeObject->setSlot(i, val); } } val.setObject(*object); iter.storeInstructionResult(val); return true; }
bool RNewObject::recover(JSContext *cx, SnapshotIterator &iter) const { RootedNativeObject templateObject(cx, &iter.read().toObject().as<NativeObject>()); RootedValue result(cx); JSObject *resultObject = nullptr; // See CodeGenerator::visitNewObjectVMCall if (templateObjectIsClassPrototype_) resultObject = NewInitObjectWithClassPrototype(cx, templateObject); else resultObject = NewInitObject(cx, templateObject); if (!resultObject) return false; result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RCreateThisWithTemplate::recover(JSContext *cx, SnapshotIterator &iter) const { RootedNativeObject templateObject(cx, &iter.read().toObject().as<NativeObject>()); // Use AutoEnterAnalysis to avoid invoking the object metadata callback // while bailing out, which could try to walk the stack. types::AutoEnterAnalysis enter(cx); // See CodeGenerator::visitCreateThisWithTemplate gc::AllocKind allocKind = templateObject->asTenured().getAllocKind(); gc::InitialHeap initialHeap = tenuredHeap_ ? gc::TenuredHeap : gc::DefaultHeap; JSObject *resultObject = NativeObject::copy(cx, allocKind, initialHeap, templateObject); if (!resultObject) return false; RootedValue result(cx); result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RSignExtend::recover(JSContext* cx, SnapshotIterator& iter) const { RootedValue operand(cx, iter.read()); int32_t result; switch (MSignExtend::Mode(mode_)) { case MSignExtend::Byte: if (!js::SignExtendOperation<int8_t>(cx, operand, &result)) return false; break; case MSignExtend::Half: if (!js::SignExtendOperation<int16_t>(cx, operand, &result)) return false; break; } RootedValue rootedResult(cx, js::Int32Value(result)); iter.storeInstructionResult(rootedResult); return true; }
bool RStringSplit::recover(JSContext *cx, SnapshotIterator &iter) const { RootedString str(cx, iter.read().toString()); RootedString sep(cx, iter.read().toString()); RootedTypeObject typeObj(cx, iter.read().toObject().type()); RootedValue result(cx); // Use AutoEnterAnalysis to avoid invoking the object metadata callback, // which could try to walk the stack while bailing out. types::AutoEnterAnalysis enter(cx); JSObject *res = str_split_string(cx, typeObj, str, sep); if (!res) return false; result.setObject(*res); iter.storeInstructionResult(result); return true; }
bool RNewObject::recover(JSContext* cx, SnapshotIterator& iter) const { RootedObject templateObject(cx, &iter.read().toObject()); RootedValue result(cx); JSObject* resultObject = nullptr; // See CodeGenerator::visitNewObjectVMCall if (mode_ == MNewObject::ObjectLiteral) { resultObject = NewObjectOperationWithTemplate(cx, templateObject); } else { MOZ_ASSERT(mode_ == MNewObject::ObjectCreate); resultObject = ObjectCreateWithTemplate(cx, templateObject.as<PlainObject>()); } if (!resultObject) return false; result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RArrayState::recover(JSContext *cx, SnapshotIterator &iter) const { RootedValue result(cx); ArrayObject *object = &iter.read().toObject().as<ArrayObject>(); uint32_t initLength = iter.read().toInt32(); object->setDenseInitializedLength(initLength); for (size_t index = 0; index < numElements(); index++) { Value val = iter.read(); if (index >= initLength) { MOZ_ASSERT(val.isUndefined()); continue; } object->initDenseElement(index, val); } result.setObject(*object); iter.storeInstructionResult(result); return true; }
bool RNewArray::recover(JSContext *cx, SnapshotIterator &iter) const { RootedObject templateObject(cx, &iter.read().toObject()); RootedValue result(cx); RootedTypeObject type(cx); // Use AutoEnterAnalysis to avoid invoking the object metadata callback // while bailing out, which could try to walk the stack. types::AutoEnterAnalysis enter(cx); // See CodeGenerator::visitNewArrayCallVM if (!templateObject->hasSingletonType()) type = templateObject->type(); JSObject *resultObject = NewDenseArray(cx, count_, type, allocatingBehaviour_); if (!resultObject) return false; result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RSimdBox::recover(JSContext* cx, SnapshotIterator& iter) const { JSObject* resultObject = nullptr; RValueAllocation a = iter.readAllocation(); MOZ_ASSERT(iter.allocationReadable(a)); const FloatRegisters::RegisterContent* raw = iter.floatAllocationPointer(a); switch (SimdTypeDescr::Type(type_)) { case SimdTypeDescr::Int32x4: MOZ_ASSERT_IF(a.mode() == RValueAllocation::ANY_FLOAT_REG, a.fpuReg().isInt32x4()); resultObject = js::CreateSimd<Int32x4>(cx, (const Int32x4::Elem*) raw); break; case SimdTypeDescr::Float32x4: MOZ_ASSERT_IF(a.mode() == RValueAllocation::ANY_FLOAT_REG, a.fpuReg().isFloat32x4()); resultObject = js::CreateSimd<Float32x4>(cx, (const Float32x4::Elem*) raw); break; case SimdTypeDescr::Float64x2: MOZ_CRASH("NYI, RSimdBox of Float64x2"); break; case SimdTypeDescr::Int8x16: MOZ_CRASH("NYI, RSimdBox of Int8x16"); break; case SimdTypeDescr::Int16x8: MOZ_CRASH("NYI, RSimdBox of Int16x8"); break; } if (!resultObject) return false; RootedValue result(cx); result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RNewObject::recover(JSContext *cx, SnapshotIterator &iter) const { RootedObject templateObject(cx, &iter.read().toObject()); RootedValue result(cx); JSObject *resultObject = nullptr; // Use AutoEnterAnalysis to avoid invoking the object metadata callback // while bailing out, which could try to walk the stack. types::AutoEnterAnalysis enter(cx); // See CodeGenerator::visitNewObjectVMCall if (templateObjectIsClassPrototype_) resultObject = NewInitObjectWithClassPrototype(cx, templateObject); else resultObject = NewInitObject(cx, templateObject); if (!resultObject) return false; result.setObject(*resultObject); iter.storeInstructionResult(result); return true; }
bool RMul::recover(JSContext* cx, SnapshotIterator& iter) const { RootedValue lhs(cx, iter.read()); RootedValue rhs(cx, iter.read()); RootedValue result(cx); if (MMul::Mode(mode_) == MMul::Normal) { if (!js::MulValues(cx, &lhs, &rhs, &result)) return false; // MIRType_Float32 is a specialization embedding the fact that the // result is rounded to a Float32. if (isFloatOperation_ && !RoundFloat32(cx, result, &result)) return false; } else { MOZ_ASSERT(MMul::Mode(mode_) == MMul::Integer); if (!js::math_imul_handle(cx, lhs, rhs, &result)) return false; } iter.storeInstructionResult(result); return true; }