bool TypeInferenceOracle::propertyReadIdempotent(HandleScript script, jsbytecode *pc, HandleId id) { if (script->analysis()->getCode(pc).notIdempotent) return false; if (id != MakeTypeId(cx, id)) return false; StackTypeSet *types = script->analysis()->poppedTypes(pc, 0); if (!types || types->unknownObject()) return false; for (unsigned i = 0; i < types->getObjectCount(); i++) { if (types->getSingleObject(i)) return false; if (TypeObject *obj = types->getTypeObject(i)) { if (obj->unknownProperties()) return false; // Check if the property has been reconfigured or is a getter. HeapTypeSet *propertyTypes = obj->getProperty(cx, id, false); if (!propertyTypes || propertyTypes->isOwnProperty(cx, obj, true)) return false; } } return true; }
bool TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc) { JS_ASSERT(types::IsInlinableCall(pc)); Bytecode *code = caller->analysis()->maybeCode(pc); if (code->monitoredTypes || code->monitoredTypesReturn || caller->analysis()->typeBarriers(cx, pc)) return false; return true; }
bool TypeInferenceOracle::elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *arrayType) { // Check whether the object is a typed array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1); StackTypeSet *id = DropUnrooted(script)->analysis()->poppedTypes(pc, 0); JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; *arrayType = obj->getTypedArrayType(); if (*arrayType == TypedArray::TYPE_MAX) return false; JS_ASSERT(*arrayType >= 0 && *arrayType < TypedArray::TYPE_MAX); // Unlike dense arrays, the types of elements in typed arrays are not // guaranteed to be present in the object's type, and we need to use // knowledge about the possible contents of the array vs. the types // that have been read out of it to figure out how to do the load. types::TypeSet *result = propertyRead(script, pc); if (*arrayType == TypedArray::TYPE_FLOAT32 || *arrayType == TypedArray::TYPE_FLOAT64) { if (!result->hasType(types::Type::DoubleType())) return false; } else { if (!result->hasType(types::Type::Int32Type())) return false; } return true; }
bool TypeInferenceOracle::elementWriteIsDenseArray(HandleScript script, jsbytecode *pc) { // Check whether the object is a dense array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2); StackTypeSet *id = script->analysis()->poppedTypes(pc, 1); JSValueType objType = obj->getKnownTypeTag(); if (objType != JSVAL_TYPE_OBJECT) return false; JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY); }
bool TypeInferenceOracle::inObjectIsDenseNativeWithoutExtraIndexedProperties(HandleScript script, jsbytecode *pc) { // Check whether the object is a native and index is int32 or double. StackTypeSet *id = script->analysis()->poppedTypes(pc, 1); StackTypeSet *obj = script->analysis()->poppedTypes(pc, 0); JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; Class *clasp = obj->getKnownClass(); if (!clasp || !clasp->isNative()) return false; return !types::TypeCanHaveExtraIndexedProperties(cx, obj); }
bool TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode *pc) { // Check whether the object is a dense array and index is int32 or double. StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2); StackTypeSet *id = script->analysis()->poppedTypes(pc, 1); JSValueType idType = id->getKnownTypeTag(); if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE) return false; Class *clasp = obj->getKnownClass(); if (!clasp || !clasp->isNative()) return false; return obj->convertDoubleElements(cx) != StackTypeSet::AmbiguousDoubleConversion; }
bool TypeInferenceOracle::canInlineCall(HandleScript caller, jsbytecode *pc) { JS_ASSERT(types::IsInlinableCall(pc)); JSOp op = JSOp(*pc); Bytecode *code = caller->analysis()->maybeCode(pc); // For foo.apply(this, arguments), the caller is foo and not the js_fun_apply function. // Ignore code->monitoredTypes, as we know the caller is foo if (op != JSOP_FUNAPPLY && code->monitoredTypes) return false; // Gets removed in Bug 796114 if (caller->analysis()->typeBarriers(cx, pc)) return false; return true; }
bool TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode *pc) { return elementWriteIsDenseNative(script->analysis()->poppedTypes(pc, 2), script->analysis()->poppedTypes(pc, 1)); }