int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue) { JSValue value = JSValue::decode(encodedValue); if (!value.isDouble()) return JSValue::notInt52; return tryConvertToInt52(value.asDouble()); }
ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) { JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); JSValue baseValue = JSValue::decode(encodedBase); JSValue property = JSValue::decode(encodedProperty); JSValue value = JSValue::decode(encodedValue); if (LIKELY(property.isUInt32())) { putByVal<strict>(exec, baseValue, property.asUInt32(), value); return; } if (property.isDouble()) { double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsDouble == propertyAsUInt32) { putByVal<strict>(exec, baseValue, propertyAsUInt32, value); return; } } // Don't put to an object if toString throws an exception. Identifier ident(exec, property.toString(exec)->value(exec)); if (!globalData->exception) { PutPropertySlot slot(strict); baseValue.put(exec, ident, value, slot); } }
EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty) { VM& vm = exec->vm(); NativeCallFrameTracer tracer(&vm, exec); JSValue property = JSValue::decode(encodedProperty); if (property.isUInt32()) return getByVal(exec, base, property.asUInt32()); if (property.isDouble()) { double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsUInt32 == propertyAsDouble) return getByVal(exec, base, propertyAsUInt32); } else if (property.isString()) { Structure& structure = *base->structure(vm); if (JSCell::canUseFastGetOwnProperty(structure)) { if (AtomicStringImpl* existingAtomicString = asString(property)->toExistingAtomicString(exec)) { if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString)) return JSValue::encode(result); } } } PropertyName propertyName = property.toPropertyKey(exec); return JSValue::encode(JSValue(base).get(exec, propertyName)); }
static CodeBlock* codeBlockFromArg(ExecState* exec) { VM& vm = exec->vm(); if (exec->argumentCount() < 1) return nullptr; JSValue value = exec->uncheckedArgument(0); CodeBlock* candidateCodeBlock = nullptr; if (value.isCell()) { JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell()); if (func) { if (func->isHostFunction()) candidateCodeBlock = nullptr; else candidateCodeBlock = func->jsExecutable()->eitherCodeBlock(); } } else if (value.isDouble()) { // If the value is a double, it may be an encoded CodeBlock* that came from // $vm.codeBlockForFrame(). We'll treat it as a candidate codeBlock and check if it's // valid below before using. candidateCodeBlock = reinterpret_cast<CodeBlock*>(bitwise_cast<uint64_t>(value.asDouble())); } if (candidateCodeBlock && JSDollarVMPrototype::isValidCodeBlock(exec, candidateCodeBlock)) return candidateCodeBlock; if (candidateCodeBlock) dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n"); else dataLog("Invalid codeBlock: ", value, "\n"); return nullptr; }
ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) { VM* vm = &exec->vm(); NativeCallFrameTracer tracer(vm, exec); JSValue baseValue = JSValue::decode(encodedBase); JSValue property = JSValue::decode(encodedProperty); JSValue value = JSValue::decode(encodedValue); if (LIKELY(property.isUInt32())) { putByVal<strict, direct>(exec, baseValue, property.asUInt32(), value); return; } if (property.isDouble()) { double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsDouble == propertyAsUInt32) { putByVal<strict, direct>(exec, baseValue, propertyAsUInt32, value); return; } } // Don't put to an object if toString throws an exception. PropertyName propertyName = property.toPropertyKey(exec); if (!vm->exception()) { PutPropertySlot slot(baseValue, strict); if (direct) { RELEASE_ASSERT(baseValue.isObject()); asObject(baseValue)->putDirect(*vm, propertyName, value, slot); } else baseValue.put(exec, propertyName, value, slot); } }
EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) { JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); JSValue baseValue = JSValue::decode(encodedBase); JSValue property = JSValue::decode(encodedProperty); if (LIKELY(baseValue.isCell())) { JSCell* base = baseValue.asCell(); if (property.isUInt32()) { return getByVal(exec, base, property.asUInt32()); } else if (property.isDouble()) { double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsUInt32 == propertyAsDouble) return getByVal(exec, base, propertyAsUInt32); } else if (property.isString()) { if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec))) return JSValue::encode(result); } } Identifier ident(exec, property.toString(exec)->value(exec)); return JSValue::encode(baseValue.get(exec, ident)); }
void dumpImmediate(JSValue value) { if (value.isNull()) write(NullTag); else if (value.isUndefined()) write(UndefinedTag); else if (value.isNumber()) { if (value.isInt32()) { if (!value.asInt32()) write(ZeroTag); else if (value.asInt32() == 1) write(OneTag); else { write(IntTag); write(static_cast<uint32_t>(value.asInt32())); } } else { write(DoubleTag); write(value.asDouble()); } } else if (value.isBoolean()) { if (value.isTrue()) write(TrueTag); else write(FalseTag); } }
char* JIT_OPERATION operationFindSwitchImmTargetForDouble( ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex) { CodeBlock* codeBlock = exec->codeBlock(); SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex); JSValue value = JSValue::decode(encodedValue); ASSERT(value.isDouble()); double asDouble = value.asDouble(); int32_t asInt32 = static_cast<int32_t>(asDouble); if (asDouble == asInt32) return static_cast<char*>(table.ctiForValue(asInt32).executableAddress()); return static_cast<char*>(table.ctiDefault.executableAddress()); }
// ECMA-262 20.1.2.5 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsSafeInteger(ExecState* exec) { JSValue argument = exec->argument(0); bool isInteger; if (argument.isInt32()) isInteger = true; else if (!argument.isDouble()) isInteger = false; else { double number = argument.asDouble(); isInteger = trunc(number) == number && std::abs(number) <= 9007199254740991.0; } return JSValue::encode(jsBoolean(isInteger)); }
// ECMA-262 20.1.2.3 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsInteger(ExecState* exec) { JSValue argument = exec->argument(0); bool isInteger; if (argument.isInt32()) isInteger = true; else if (!argument.isDouble()) isInteger = false; else { double number = argument.asDouble(); isInteger = std::isfinite(number) && trunc(number) == number; } return JSValue::encode(jsBoolean(isInteger)); }
EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty) { JSValue property = JSValue::decode(encodedProperty); if (property.isUInt32()) return getByVal(exec, base, property.asUInt32()); if (property.isDouble()) { double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsUInt32 == propertyAsDouble) return getByVal(exec, base, propertyAsUInt32); } else if (property.isString()) { if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec))) return JSValue::encode(result); } Identifier ident(exec, property.toString(exec)); return JSValue::encode(JSValue(base).get(exec, ident)); }
static ALWAYS_INLINE bool toThisNumber(JSValue thisValue, double& x) { if (thisValue.isInt32()) { x = thisValue.asInt32(); return true; } if (thisValue.isDouble()) { x = thisValue.asDouble(); return true; } if (thisValue.isCell() && thisValue.asCell()->type() == NumberObjectType) { x = static_cast<const NumberObject*>(thisValue.asCell())->internalValue().asNumber(); return true; } return false; }
static CodeBlock* codeBlockFromArg(ExecState* exec) { if (exec->argumentCount() < 1) return nullptr; JSValue value = exec->uncheckedArgument(0); if (!value.isDouble()) { dataLog("Invalid codeBlock: ", value, "\n"); return nullptr; } CodeBlock* codeBlock = reinterpret_cast<CodeBlock*>(bitwise_cast<uint64_t>(value.asDouble())); if (JSDollarVMPrototype::isValidCodeBlock(exec, codeBlock)) return codeBlock; dataLogF("Invalid codeBlock: %p ", codeBlock); dataLog(value, "\n"); return nullptr; }
ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) { VM* vm = &exec->vm(); NativeCallFrameTracer tracer(vm, exec); JSValue baseValue = JSValue::decode(encodedBase); JSValue property = JSValue::decode(encodedProperty); JSValue value = JSValue::decode(encodedValue); if (LIKELY(property.isUInt32())) { // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices. ASSERT(isIndex(property.asUInt32())); putByVal<strict, direct>(exec, baseValue, property.asUInt32(), value); return; } if (property.isDouble()) { double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) { putByVal<strict, direct>(exec, baseValue, propertyAsUInt32, value); return; } } // Don't put to an object if toString throws an exception. auto propertyName = property.toPropertyKey(exec); if (vm->exception()) return; PutPropertySlot slot(baseValue, strict); if (direct) { RELEASE_ASSERT(baseValue.isObject()); if (Optional<uint32_t> index = parseIndex(propertyName)) asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow); else asObject(baseValue)->putDirect(*vm, propertyName, value, slot); } else baseValue.put(exec, propertyName, value, slot); }
EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) { VM& vm = exec->vm(); NativeCallFrameTracer tracer(&vm, exec); JSValue baseValue = JSValue::decode(encodedBase); JSValue property = JSValue::decode(encodedProperty); if (LIKELY(baseValue.isCell())) { JSCell* base = baseValue.asCell(); if (property.isUInt32()) { return getByVal(exec, base, property.asUInt32()); } else if (property.isDouble()) { double propertyAsDouble = property.asDouble(); uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble); if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32)) return getByVal(exec, base, propertyAsUInt32); } else if (property.isString()) { Structure& structure = *base->structure(vm); if (JSCell::canUseFastGetOwnProperty(structure)) { if (AtomicStringImpl* existingAtomicString = asString(property)->toExistingAtomicString(exec)) { if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString)) return JSValue::encode(result); } } } } baseValue.requireObjectCoercible(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); auto propertyName = property.toPropertyKey(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); return JSValue::encode(baseValue.get(exec, propertyName)); }
// ECMA-262 20.1.2.4 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsNaN(ExecState* exec) { JSValue argument = exec->argument(0); return JSValue::encode(jsBoolean(argument.isDouble() && std::isnan(argument.asDouble()))); }
// ECMA-262 20.1.2.2 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsFinite(ExecState* exec) { JSValue argument = exec->argument(0); return JSValue::encode(jsBoolean(argument.isNumber() && (argument.isInt32() || std::isfinite(argument.asDouble())))); }