Exemple #1
0
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));
}
Exemple #2
0
int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
{
    JSValue value = JSValue::decode(encodedValue);
    if (!value.isDouble())
        return JSValue::notInt52;
    return tryConvertToInt52(value.asDouble());
}
Exemple #3
0
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);
    }
}
Exemple #4
0
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);
    }
}
Exemple #5
0
SpeculatedType speculationFromValue(JSValue value)
{
    if (value.isEmpty())
        return SpecEmpty;
    if (value.isInt32())
        return SpecInt32;
    if (value.isDouble()) {
        double number = value.asNumber();
        if (number == number) {
            int64_t asInt64 = static_cast<int64_t>(number);
            if (asInt64 == number && (asInt64 || !std::signbit(number))
                && asInt64 < (static_cast<int64_t>(1) << 47)
                && asInt64 >= -(static_cast<int64_t>(1) << 47)) {
                return SpecInt48AsDouble;
            }
            return SpecNonIntAsDouble;
        }
        return SpecDoubleNaN;
    }
    if (value.isCell())
        return speculationFromCell(value.asCell());
    if (value.isBoolean())
        return SpecBoolean;
    ASSERT(value.isUndefinedOrNull());
    return SpecOther;
}
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;
}
Exemple #7
0
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));
}
static RefPtr<InspectorValue> jsToInspectorValue(ExecState* scriptState, JSValue value, int maxDepth)
{
    if (!value) {
        ASSERT_NOT_REACHED();
        return nullptr;
    }

    if (!maxDepth)
        return nullptr;

    maxDepth--;

    if (value.isNull() || value.isUndefined())
        return InspectorValue::null();
    if (value.isBoolean())
        return InspectorValue::create(value.asBoolean());
    if (value.isNumber() && value.isDouble())
        return InspectorValue::create(value.asNumber());
    if (value.isNumber() && value.isMachineInt())
        return InspectorValue::create(static_cast<int>(value.asMachineInt()));
    if (value.isString())
        return InspectorValue::create(value.getString(scriptState));

    if (value.isObject()) {
        if (isJSArray(value)) {
            Ref<InspectorArray> inspectorArray = InspectorArray::create();
            JSArray* array = asArray(value);
            unsigned length = array->length();
            for (unsigned i = 0; i < length; i++) {
                JSValue element = array->getIndex(scriptState, i);
                RefPtr<InspectorValue> elementValue = jsToInspectorValue(scriptState, element, maxDepth);
                if (!elementValue)
                    return nullptr;
                inspectorArray->pushValue(WTFMove(elementValue));
            }
            return WTFMove(inspectorArray);
        }
        Ref<InspectorObject> inspectorObject = InspectorObject::create();
        JSObject* object = value.getObject();
        PropertyNameArray propertyNames(scriptState, PropertyNameMode::Strings);
        object->methodTable()->getOwnPropertyNames(object, scriptState, propertyNames, EnumerationMode());
        for (size_t i = 0; i < propertyNames.size(); i++) {
            const Identifier& name = propertyNames[i];
            JSValue propertyValue = object->get(scriptState, name);
            RefPtr<InspectorValue> inspectorValue = jsToInspectorValue(scriptState, propertyValue, maxDepth);
            if (!inspectorValue)
                return nullptr;
            inspectorObject->setValue(name.string(), WTFMove(inspectorValue));
        }
        return WTFMove(inspectorObject);
    }

    ASSERT_NOT_REACHED();
    return nullptr;
}
PredictedType predictionFromValue(JSValue value)
{
    if (value.isInt32())
        return PredictInt32;
    if (value.isDouble())
        return PredictDouble;
    if (value.isCell())
        return predictionFromCell(value.asCell());
    if (value.isBoolean())
        return PredictBoolean;
    ASSERT(value.isUndefinedOrNull());
    return PredictOther;
}
Exemple #10
0
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));
}
Exemple #13
0
PredictedType predictionFromValue(JSValue value)
{
    if (value.isInt32())
        return PredictInt32;
    if (value.isDouble()) {
        double number = value.asNumber();
        if (number == number)
            return PredictDoubleReal;
        return PredictDoubleNaN;
    }
    if (value.isCell())
        return predictionFromCell(value.asCell());
    if (value.isBoolean())
        return PredictBoolean;
    ASSERT(value.isUndefinedOrNull());
    return PredictOther;
}
Exemple #14
0
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;
}
Exemple #16
0
void ValueProfile::computeStatistics(Statistics& statistics) const
{
    for (unsigned i = 0; i < numberOfBuckets; ++i) {
        JSValue value = JSValue::decode(m_buckets[i]);
        if (!value)
            continue;
        
        statistics.samples++;
        
        if (value.isInt32())
            statistics.int32s++;
        else if (value.isDouble())
            statistics.doubles++;
        else if (value.isCell())
            computeStatistics(value.asCell()->structure()->classInfo(), statistics);
        else if (value.isBoolean())
            statistics.booleans++;
    }
}
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;
    
}
Exemple #18
0
SpeculatedType speculationFromValue(JSValue value)
{
    if (value.isEmpty())
        return SpecEmpty;
    if (value.isInt32())
        return SpecInt32;
    if (value.isDouble()) {
        double number = value.asNumber();
        if (number != number)
            return SpecDoubleNaN;
        if (value.isMachineInt())
            return SpecInt52AsDouble;
        return SpecNonIntAsDouble;
    }
    if (value.isCell())
        return speculationFromCell(value.asCell());
    if (value.isBoolean())
        return SpecBoolean;
    ASSERT(value.isUndefinedOrNull());
    return SpecOther;
}
Exemple #19
0
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);
}
Exemple #20
0
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())));
}