From 2e26ebc0fc064092691426162626a19233891216 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Fri, 16 May 2014 13:52:49 -0700 Subject: [PATCH] Backed out 4 changesets (bug 973238) for build bustage on a CLOSED TREE Backed out changeset cc81a0f56362 (bug 973238) Backed out changeset 472dffac7f21 (bug 973238) Backed out changeset e40e2dbf7d9e (bug 973238) Backed out changeset 2ca44eb13ecf (bug 973238) --- js/src/builtin/TypedObject.cpp | 17 ++- js/src/builtin/TypedObject.h | 6 +- js/src/builtin/TypedObject.js | 33 +++--- js/src/builtin/TypedObjectConstants.h | 2 +- js/src/gc/Marking.cpp | 4 + .../jit-test/tests/TypedObject/prototypes.js | 13 +-- js/src/jit/CodeGenerator.cpp | 17 --- js/src/jit/CodeGenerator.h | 1 - js/src/jit/IonBuilder.cpp | 26 ++--- js/src/jit/LIR-Common.h | 19 ---- js/src/jit/LOpcodes.h | 1 - js/src/jit/Lowering.cpp | 10 -- js/src/jit/Lowering.h | 1 - js/src/jit/MIR.h | 33 ------ js/src/jit/MOpcodes.h | 1 - js/src/jit/ParallelSafetyAnalysis.cpp | 1 - js/src/jit/VMFunctions.cpp | 9 -- js/src/jit/VMFunctions.h | 2 - js/src/jsinfer.cpp | 100 ++++++++++++++---- js/src/jsinfer.h | 48 ++++++++- js/src/jsinferinlines.h | 3 + js/src/vm/TypedArrayObject.h | 2 +- 22 files changed, 170 insertions(+), 179 deletions(-) diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 1889ce2a324..ee33dfecc59 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -822,7 +822,8 @@ js::IsTypedObjectArray(JSObject &obj) const Class StructTypeDescr::class_ = { "StructType", - JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS), + JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | + JSCLASS_HAS_PRIVATE, // used to store FieldList JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, @@ -1483,6 +1484,17 @@ TypedObject::createUnattachedWithClass(JSContext *cx, obj->initReservedSlot(JS_TYPEDOBJ_SLOT_OWNER, NullValue()); obj->initReservedSlot(JS_TYPEDOBJ_SLOT_NEXT_VIEW, PrivateValue(nullptr)); obj->initReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(length)); + obj->initReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR, ObjectValue(*type)); + + // Tag the type object for this instance with the type + // representation, if that has not been done already. + if (!type->is()) { // FIXME Bug 929651 + RootedTypeObject typeObj(cx, obj->getType(cx)); + if (typeObj) { + if (!typeObj->addTypedObjectAddendum(cx, type)) + return nullptr; + } + } return static_cast(&*obj); } @@ -1626,6 +1638,9 @@ ReportTypedObjTypeError(JSContext *cx, /*static*/ void TypedObject::obj_trace(JSTracer *trace, JSObject *object) { + gc::MarkSlot(trace, &object->getReservedSlotRef(JS_TYPEDOBJ_SLOT_TYPE_DESCR), + "TypedObjectTypeDescr"); + ArrayBufferViewObject::trace(trace, object); JS_ASSERT(object->is()); diff --git a/js/src/builtin/TypedObject.h b/js/src/builtin/TypedObject.h index c01dc48cc70..a0bcdaca135 100644 --- a/js/src/builtin/TypedObject.h +++ b/js/src/builtin/TypedObject.h @@ -655,12 +655,8 @@ class TypedObject : public ArrayBufferViewObject return getReservedSlot(JS_TYPEDOBJ_SLOT_OWNER).toObject().as(); } - TypedProto &typedProto() const { - return getProto()->as(); - } - TypeDescr &typeDescr() const { - return typedProto().typeDescr(); + return getReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR).toObject().as(); } uint8_t *typedMem() const { diff --git a/js/src/builtin/TypedObject.js b/js/src/builtin/TypedObject.js index f7cee8d2087..f4afbd0bf5d 100644 --- a/js/src/builtin/TypedObject.js +++ b/js/src/builtin/TypedObject.js @@ -28,17 +28,14 @@ #define DESCR_STRUCT_FIELD_OFFSETS(obj) \ UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS) -// Typed prototype slots - -#define TYPROTO_DESCR(obj) \ - UnsafeGetReservedSlot(obj, JS_TYPROTO_SLOT_DESCR) - // Typed object slots #define TYPEDOBJ_BYTEOFFSET(obj) \ TO_INT32(UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_BYTEOFFSET)) #define TYPEDOBJ_BYTELENGTH(obj) \ TO_INT32(UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_BYTELENGTH)) +#define TYPEDOBJ_TYPE_DESCR(obj) \ + UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_TYPE_DESCR) #define TYPEDOBJ_OWNER(obj) \ UnsafeGetReservedSlot(obj, JS_TYPEDOBJ_SLOT_OWNER) #define TYPEDOBJ_LENGTH(obj) \ @@ -47,10 +44,6 @@ #define HAS_PROPERTY(obj, prop) \ callFunction(std_Object_hasOwnProperty, obj, prop) -function TypedObjectTypeDescr(typedObj) { - return TYPROTO_DESCR(typedObj.__proto__); -} - /////////////////////////////////////////////////////////////////////////// // Getting values // @@ -199,7 +192,7 @@ function TypedObjectSet(descr, typedObj, offset, fromValue) { // representation as the destination. In that case, we can just do a // memcpy. if (IsObject(fromValue) && ObjectIsTypedObject(fromValue)) { - if (!descr.variable && DescrsEquiv(descr, TypedObjectTypeDescr(fromValue))) { + if (!descr.variable && DescrsEquiv(descr, TYPEDOBJ_TYPE_DESCR(fromValue))) { if (!TypedObjectIsAttached(fromValue)) ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED); @@ -393,7 +386,7 @@ function FillTypedArrayWithValue(destArray, fromValue) { assert(IsObject(handle) && ObjectIsTypedObject(destArray), "FillTypedArrayWithValue: not typed handle"); - var descr = TypedObjectTypeDescr(destArray); + var descr = TYPEDOBJ_TYPE_DESCR(destArray); var length = DESCR_SIZED_ARRAY_LENGTH(descr); if (length === 0) return; @@ -447,7 +440,7 @@ function TypedArrayRedimension(newArrayType) { // Peel away the outermost array layers from the type of `this` to find // the core element type. In the process, count the number of elements. - var oldArrayType = TypedObjectTypeDescr(this); + var oldArrayType = TYPEDOBJ_TYPE_DESCR(this); var oldArrayReprKind = DESCR_KIND(oldArrayType); var oldElementType = oldArrayType; var oldElementCount = 1; @@ -514,7 +507,7 @@ function X4ToSource() { if (!IsObject(this) || !ObjectIsTypedObject(this)) ThrowError(JSMSG_INCOMPATIBLE_PROTO, "X4", "toSource", typeof this); - var descr = TypedObjectTypeDescr(this); + var descr = TYPEDOBJ_TYPE_DESCR(this); if (DESCR_KIND(descr) != JS_TYPEREPR_X4_KIND) ThrowError(JSMSG_INCOMPATIBLE_PROTO, "X4", "toSource", typeof this); @@ -592,7 +585,7 @@ function StorageOfTypedObject(obj) { // Warning: user exposed! function TypeOfTypedObject(obj) { if (IsObject(obj) && ObjectIsTypedObject(obj)) - return TypedObjectTypeDescr(obj); + return TYPEDOBJ_TYPE_DESCR(obj); // Note: Do not create bindings for `Any`, `String`, etc in // Utilities.js, but rather access them through @@ -686,7 +679,7 @@ function TypedObjectArrayTypeFrom(a, b, c) { function TypedArrayMap(a, b) { if (!IsObject(this) || !ObjectIsTypedObject(this)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - var thisType = TypedObjectTypeDescr(this); + var thisType = TYPEDOBJ_TYPE_DESCR(this); if (!TypeDescrIsArrayType(thisType)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -706,7 +699,7 @@ function TypedArrayMapPar(a, b) { // when not working with typed objects. if (!IsObject(this) || !ObjectIsTypedObject(this)) return callFunction(TypedArrayMap, this, a, b); - var thisType = TypedObjectTypeDescr(this); + var thisType = TYPEDOBJ_TYPE_DESCR(this); if (!TypeDescrIsArrayType(thisType)) return callFunction(TypedArrayMap, this, a, b); @@ -722,7 +715,7 @@ function TypedArrayReduce(a, b) { // Arguments: func, [initial] if (!IsObject(this) || !ObjectIsTypedObject(this)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - var thisType = TypedObjectTypeDescr(this); + var thisType = TYPEDOBJ_TYPE_DESCR(this); if (!TypeDescrIsArrayType(thisType)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -738,7 +731,7 @@ function TypedArrayScatter(a, b, c, d) { // Arguments: outputArrayType, indices, defaultValue, conflictFunction if (!IsObject(this) || !ObjectIsTypedObject(this)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - var thisType = TypedObjectTypeDescr(this); + var thisType = TYPEDOBJ_TYPE_DESCR(this); if (!TypeDescrIsArrayType(thisType)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -756,7 +749,7 @@ function TypedArrayFilter(func) { // Arguments: predicate if (!IsObject(this) || !ObjectIsTypedObject(this)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); - var thisType = TypedObjectTypeDescr(this); + var thisType = TYPEDOBJ_TYPE_DESCR(this); if (!TypeDescrIsArrayType(thisType)) return ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS); @@ -1139,7 +1132,7 @@ function RedirectPointer(typedObj, offset, outputIsScalar) { // is an overapproximation: users can manually declare opaque // types that nonetheless only contain scalar data. - typedObj = NewDerivedTypedObject(TypedObjectTypeDescr(typedObj), + typedObj = NewDerivedTypedObject(TYPEDOBJ_TYPE_DESCR(typedObj), typedObj, 0); } diff --git a/js/src/builtin/TypedObjectConstants.h b/js/src/builtin/TypedObjectConstants.h index 8b57a60b4c9..9d4868a7981 100644 --- a/js/src/builtin/TypedObjectConstants.h +++ b/js/src/builtin/TypedObjectConstants.h @@ -99,7 +99,7 @@ #define JS_DATAVIEW_SLOTS 4 // Number of slots for data views #define JS_TYPEDOBJ_SLOT_LENGTH 4 // Length of array (see (*) below) -#define JS_TYPEDARR_SLOT_TYPE 5 // For typed arrays only, type code +#define JS_TYPEDOBJ_SLOT_TYPE_DESCR 5 // For typed objects, type descr #define JS_TYPEDOBJ_SLOT_DATA 7 // private slot, based on alloc kind #define JS_TYPEDOBJ_SLOTS 6 // Number of slots for typed objs diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index bfa938f1c3d..824fda3d57d 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -1259,6 +1259,8 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type) if (type->hasNewScript()) { PushMarkStack(gcmarker, type->newScript()->fun); PushMarkStack(gcmarker, type->newScript()->templateObject); + } else if (type->hasTypedObject()) { + PushMarkStack(gcmarker, type->typedObject()->descrHeapPtr()); } if (type->interpretedFunction) @@ -1284,6 +1286,8 @@ gc::MarkChildren(JSTracer *trc, types::TypeObject *type) if (type->hasNewScript()) { MarkObject(trc, &type->newScript()->fun, "type_new_function"); MarkObject(trc, &type->newScript()->templateObject, "type_new_template"); + } else if (type->hasTypedObject()) { + MarkObject(trc, &type->typedObject()->descrHeapPtr(), "type_heap_ptr"); } if (type->interpretedFunction) diff --git a/js/src/jit-test/tests/TypedObject/prototypes.js b/js/src/jit-test/tests/TypedObject/prototypes.js index 3910ecf6c44..452c30b6c15 100644 --- a/js/src/jit-test/tests/TypedObject/prototypes.js +++ b/js/src/jit-test/tests/TypedObject/prototypes.js @@ -1,12 +1,9 @@ // API Surface Test: check that mutating prototypes -// of type objects has no effect, and that mutating -// the prototypes of typed objects is an error. +// of type descriptors has no effect. if (!this.hasOwnProperty("TypedObject")) quit(); -load(libdir + "asserts.js"); - var {StructType, uint32, Object, Any, storage, objectType} = TypedObject; function main() { // once a C programmer, always a C programmer. @@ -15,14 +12,6 @@ function main() { // once a C programmer, always a C programmer. Uints.prototype = {}; // no effect assertEq(p, Uints.prototype); - var uints = new Uints(); - assertEq(uints.__proto__, p); - assertThrowsInstanceOf(function() uints.__proto__ = {}, - TypeError); - assertThrowsInstanceOf(function() Object.setPrototypeOf(uints, {}), - TypeError); - assertEq(uints.__proto__, p); - var Uintss = Uints.array(2); var p = Uintss.prototype; Uintss.prototype = {}; // no effect diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 63294a79f85..c6818a0e576 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -4306,23 +4306,6 @@ CodeGenerator::visitNeuterCheck(LNeuterCheck *lir) return true; } -bool -CodeGenerator::visitTypedObjectProto(LTypedObjectProto *lir) -{ - Register obj = ToRegister(lir->object()); - JS_ASSERT(ToRegister(lir->output()) == ReturnReg); - - // Eventually we ought to inline this helper function for - // efficiency, but it's mildly non-trivial since we must reach - // into the type object and so on. - - const Register tempReg = ToRegister(lir->temp()); - masm.setupUnalignedABICall(1, tempReg); - masm.passABIArg(obj); - masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, TypedObjectProto)); - return true; -} - bool CodeGenerator::visitTypedObjectElements(LTypedObjectElements *lir) { diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index c6e711beb59..ca25c405b80 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -171,7 +171,6 @@ class CodeGenerator : public CodeGeneratorSpecific bool visitNeuterCheck(LNeuterCheck *lir); bool visitTypedObjectElements(LTypedObjectElements *lir); bool visitSetTypedObjectOffset(LSetTypedObjectOffset *lir); - bool visitTypedObjectProto(LTypedObjectProto *ins); bool visitStringLength(LStringLength *lir); bool visitInitializedLength(LInitializedLength *lir); bool visitSetInitializedLength(LSetInitializedLength *lir); diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index db13e3d5986..4f723ec0e74 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -10250,20 +10250,14 @@ IonBuilder::typeSetToTypeDescrSet(types::TemporaryTypeSet *types, TypeDescrSetBuilder set; for (uint32_t i = 0; i < types->getObjectCount(); i++) { types::TypeObject *type = types->getTypeObject(i); - if (!type) + if (!type || type->unknownProperties()) return true; - if (!IsTypedObjectClass(type->clasp())) + if (!type->hasTypedObject()) return true; - TaggedProto proto = type->proto(); - - // typed objects have immutable prototypes, and they are - // always instances of TypedProto - JS_ASSERT(proto.isObject() && proto.toObject()->is()); - - TypedProto &typedProto = proto.toObject()->as(); - if (!set.insert(&typedProto.typeDescr())) + TypeDescr &descr = type->typedObject()->descr(); + if (!set.insert(&descr)) return false; } @@ -10280,16 +10274,10 @@ IonBuilder::loadTypedObjectType(MDefinition *typedObj) if (typedObj->isNewDerivedTypedObject()) return typedObj->toNewDerivedTypedObject()->type(); - MInstruction *proto = MTypedObjectProto::New(alloc(), typedObj); - current->add(proto); - - MInstruction *load = MLoadFixedSlot::New(alloc(), proto, JS_TYPROTO_SLOT_DESCR); + MInstruction *load = MLoadFixedSlot::New(alloc(), typedObj, + JS_TYPEDOBJ_SLOT_TYPE_DESCR); current->add(load); - - MInstruction *unbox = MUnbox::New(alloc(), load, MIRType_Object, MUnbox::Infallible); - current->add(unbox); - - return unbox; + return load; } // Given a typed object `typedObj` and an offset `offset` into that diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index d964d140ffc..613cfd848f6 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -3694,25 +3694,6 @@ class LTypedArrayElements : public LInstructionHelper<1, 1, 0> } }; -// Load a typed object's prototype, which is guaranteed to be a -// TypedProto object. -class LTypedObjectProto : public LCallInstructionHelper<1, 1, 1> -{ - public: - LIR_HEADER(TypedObjectProto) - - LTypedObjectProto(const LAllocation &object, const LDefinition &temp1) { - setOperand(0, object); - setTemp(0, temp1); - } - const LAllocation *object() { - return getOperand(0); - } - const LDefinition *temp() { - return getTemp(0); - } -}; - // Load a typed array's elements vector. class LTypedObjectElements : public LInstructionHelper<1, 1, 0> { diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h index c1a42b2d4fa..ef40d50188f 100644 --- a/js/src/jit/LOpcodes.h +++ b/js/src/jit/LOpcodes.h @@ -250,7 +250,6 @@ _(SetArrayLength) \ _(TypedArrayLength) \ _(TypedArrayElements) \ - _(TypedObjectProto) \ _(TypedObjectElements) \ _(SetTypedObjectOffset) \ _(StringLength) \ diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 6aad432a53a..61f73360297 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -2361,16 +2361,6 @@ LIRGenerator::visitTypedArrayElements(MTypedArrayElements *ins) return define(new(alloc()) LTypedArrayElements(useRegisterAtStart(ins->object())), ins); } -bool -LIRGenerator::visitTypedObjectProto(MTypedObjectProto *ins) -{ - JS_ASSERT(ins->type() == MIRType_Object); - return defineReturn(new(alloc()) LTypedObjectProto( - useFixed(ins->object(), CallTempReg0), - tempFixed(CallTempReg1)), - ins); -} - bool LIRGenerator::visitTypedObjectElements(MTypedObjectElements *ins) { diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index 98cc20e52f0..238b77646c0 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -182,7 +182,6 @@ class LIRGenerator : public LIRGeneratorSpecific bool visitNeuterCheck(MNeuterCheck *lir); bool visitTypedObjectElements(MTypedObjectElements *ins); bool visitSetTypedObjectOffset(MSetTypedObjectOffset *ins); - bool visitTypedObjectProto(MTypedObjectProto *ins); bool visitInitializedLength(MInitializedLength *ins); bool visitSetInitializedLength(MSetInitializedLength *ins); bool visitNot(MNot *ins); diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 26bdda06054..b32ab6093dd 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -1617,39 +1617,6 @@ class MNewPar : public MUnaryInstruction } }; -class MTypedObjectProto - : public MUnaryInstruction, - public SingleObjectPolicy -{ - private: - MTypedObjectProto(MDefinition *object) - : MUnaryInstruction(object) - { - setResultType(MIRType_Object); - setMovable(); - } - - public: - INSTRUCTION_HEADER(TypedObjectProto) - - static MTypedObjectProto *New(TempAllocator &alloc, MDefinition *object) { - return new(alloc) MTypedObjectProto(object); - } - - TypePolicy *typePolicy() { - return this; - } - MDefinition *object() const { - return getOperand(0); - } - bool congruentTo(const MDefinition *ins) const { - return congruentIfOperandsEqual(ins); - } - AliasSet getAliasSet() const { - return AliasSet::Load(AliasSet::ObjectFields); - } -}; - // Creates a new derived type object. At runtime, this is just a call // to `BinaryBlock::createDerived()`. That is, the MIR itself does not // compile to particularly optimized code. However, using a distinct diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index b31aa329dba..00de788a4f7 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -136,7 +136,6 @@ namespace jit { _(SetArrayLength) \ _(TypedArrayLength) \ _(TypedArrayElements) \ - _(TypedObjectProto) \ _(TypedObjectElements) \ _(SetTypedObjectOffset) \ _(InitializedLength) \ diff --git a/js/src/jit/ParallelSafetyAnalysis.cpp b/js/src/jit/ParallelSafetyAnalysis.cpp index 165c550df36..ffdd88b5716 100644 --- a/js/src/jit/ParallelSafetyAnalysis.cpp +++ b/js/src/jit/ParallelSafetyAnalysis.cpp @@ -224,7 +224,6 @@ class ParallelSafetyVisitor : public MInstructionVisitor WRITE_GUARDED_OP(SetArrayLength, elements) SAFE_OP(TypedArrayLength) SAFE_OP(TypedArrayElements) - SAFE_OP(TypedObjectProto) SAFE_OP(TypedObjectElements) SAFE_OP(SetTypedObjectOffset) SAFE_OP(InitializedLength) diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp index 29f2d77e56c..610f9783076 100644 --- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -1155,14 +1155,5 @@ AssertValidValue(JSContext *cx, Value *v) } #endif -// Definition of the MTypedObjectProto MIR. -JSObject * -TypedObjectProto(JSObject *obj) -{ - JS_ASSERT(obj->is()); - TypedObject &typedObj = obj->as(); - return &typedObj.typedProto(); -} - } // namespace jit } // namespace js diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h index 7444cacf47d..26b287b4207 100644 --- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -690,8 +690,6 @@ void AssertValidStringPtr(JSContext *cx, JSString *str); void AssertValidValue(JSContext *cx, Value *v); #endif -JSObject *TypedObjectProto(JSObject *obj); - } // namespace jit } // namespace js diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 863ab1af019..808fdbcda2f 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -3039,29 +3039,6 @@ TypeObject::markUnknown(ExclusiveContext *cx) } } -void -TypeObject::maybeClearNewScriptAddendumOnOOM() -{ - if (!isMarked()) - return; - - if (!addendum || addendum->kind != TypeObjectAddendum::NewScript) - return; - - for (unsigned i = 0; i < getPropertyCount(); i++) { - Property *prop = getProperty(i); - if (!prop) - continue; - if (prop->types.definiteProperty()) - prop->types.setNonDataPropertyIgnoringConstraints(); - } - - // This method is called during GC sweeping, so there is no write barrier - // that needs to be triggered. - js_free(addendum); - addendum.unsafeSet(nullptr); -} - void TypeObject::clearAddendum(ExclusiveContext *cx) { @@ -3086,6 +3063,10 @@ TypeObject::clearAddendum(ExclusiveContext *cx) case TypeObjectAddendum::NewScript: clearNewScriptAddendum(cx); break; + + case TypeObjectAddendum::TypedObject: + clearTypedObjectAddendum(cx); + break; } /* We nullptr out addendum *before* freeing it so the write barrier works. */ @@ -3200,6 +3181,34 @@ TypeObject::clearNewScriptAddendum(ExclusiveContext *cx) } } +void +TypeObject::maybeClearNewScriptAddendumOnOOM() +{ + if (!isMarked()) + return; + + if (!addendum || addendum->kind != TypeObjectAddendum::NewScript) + return; + + for (unsigned i = 0; i < getPropertyCount(); i++) { + Property *prop = getProperty(i); + if (!prop) + continue; + if (prop->types.definiteProperty()) + prop->types.setNonDataPropertyIgnoringConstraints(); + } + + // This method is called during GC sweeping, so there is no write barrier + // that needs to be triggered. + js_free(addendum); + addendum.unsafeSet(nullptr); +} + +void +TypeObject::clearTypedObjectAddendum(ExclusiveContext *cx) +{ +} + void TypeObject::print() { @@ -4551,12 +4560,47 @@ TypeScript::printTypes(JSContext *cx, HandleScript script) const } #endif /* DEBUG */ +///////////////////////////////////////////////////////////////////// +// Binary data +///////////////////////////////////////////////////////////////////// + void TypeObject::setAddendum(TypeObjectAddendum *addendum) { this->addendum = addendum; } +bool +TypeObject::addTypedObjectAddendum(JSContext *cx, Handle descr) +{ + // Type descriptors are always pre-tenured. This is both because + // we expect them to live a long time and so that they can be + // safely accessed during ion compilation. + JS_ASSERT(!IsInsideNursery(cx->runtime(), descr)); + JS_ASSERT(descr); + + if (flags() & OBJECT_FLAG_ADDENDUM_CLEARED) + return true; + + JS_ASSERT(!unknownProperties()); + + if (addendum) { + JS_ASSERT(hasTypedObject()); + JS_ASSERT(&typedObject()->descr() == descr); + return true; + } + + TypeTypedObject *typedObject = js_new(descr); + if (!typedObject) + return false; + addendum = typedObject; + return true; +} + +///////////////////////////////////////////////////////////////////// +// Type object addenda constructor +///////////////////////////////////////////////////////////////////// + TypeObjectAddendum::TypeObjectAddendum(Kind kind) : kind(kind) {} @@ -4565,3 +4609,13 @@ TypeNewScript::TypeNewScript() : TypeObjectAddendum(NewScript) {} +TypeTypedObject::TypeTypedObject(Handle descr) + : TypeObjectAddendum(TypedObject), + descr_(descr) +{ +} + +TypeDescr & +js::types::TypeTypedObject::descr() { + return descr_->as(); +} diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 1c534febf25..fcdbe4ae2a7 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -812,11 +812,13 @@ struct Property }; struct TypeNewScript; +struct TypeTypedObject; struct TypeObjectAddendum { enum Kind { - NewScript + NewScript, + TypedObject }; TypeObjectAddendum(Kind kind); @@ -832,6 +834,15 @@ struct TypeObjectAddendum return (TypeNewScript*) this; } + bool isTypedObject() { + return kind == TypedObject; + } + + TypeTypedObject *asTypedObject() { + JS_ASSERT(isTypedObject()); + return (TypeTypedObject*) this; + } + static inline void writeBarrierPre(TypeObjectAddendum *type); static void writeBarrierPost(TypeObjectAddendum *newScript, void *addr) {} @@ -888,6 +899,21 @@ struct TypeNewScript : public TypeObjectAddendum static inline void writeBarrierPre(TypeNewScript *newScript); }; +struct TypeTypedObject : public TypeObjectAddendum +{ + private: + HeapPtrObject descr_; + + public: + TypeTypedObject(Handle descr); + + HeapPtrObject &descrHeapPtr() { + return descr_; + } + + TypeDescr &descr(); +}; + /* * Lazy type objects overview. * @@ -1001,8 +1027,25 @@ struct TypeObject : gc::BarrieredCell return addendum->asNewScript(); } + bool hasTypedObject() { + return addendum && addendum->isTypedObject(); + } + + TypeTypedObject *typedObject() { + return addendum->asTypedObject(); + } + void setAddendum(TypeObjectAddendum *addendum); + /* + * Tag the type object for a binary data type descriptor, instance, + * or handle with the type representation of the data it points at. + * If this type object is already tagged with a binary data addendum, + * this addendum must already be associated with the same TypeRepresentation, + * and the method has no effect. + */ + bool addTypedObjectAddendum(JSContext *cx, Handle descr); + private: /* * Properties of this object. This may contain JSID_VOID, representing the @@ -1114,9 +1157,10 @@ struct TypeObject : gc::BarrieredCell void markStateChange(ExclusiveContext *cx); void setFlags(ExclusiveContext *cx, TypeObjectFlags flags); void markUnknown(ExclusiveContext *cx); - void maybeClearNewScriptAddendumOnOOM(); void clearAddendum(ExclusiveContext *cx); void clearNewScriptAddendum(ExclusiveContext *cx); + void clearTypedObjectAddendum(ExclusiveContext *cx); + void maybeClearNewScriptAddendumOnOOM(); bool isPropertyNonData(jsid id); bool isPropertyNonWritable(jsid id); diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h index 34619cf7e79..15a01573a74 100644 --- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -1224,6 +1224,9 @@ TypeObjectAddendum::writeBarrierPre(TypeObjectAddendum *type) switch (type->kind) { case NewScript: return TypeNewScript::writeBarrierPre(type->asNewScript()); + + case TypedObject: + return TypeTypedObject::writeBarrierPre(type->asTypedObject()); } #endif } diff --git a/js/src/vm/TypedArrayObject.h b/js/src/vm/TypedArrayObject.h index 92c4101c424..b904f829a94 100644 --- a/js/src/vm/TypedArrayObject.h +++ b/js/src/vm/TypedArrayObject.h @@ -32,7 +32,7 @@ class TypedArrayObject : public ArrayBufferViewObject // Typed array properties stored in slots, beyond those shared by all // ArrayBufferViews. static const size_t LENGTH_SLOT = JS_TYPEDOBJ_SLOT_LENGTH; - static const size_t TYPE_SLOT = JS_TYPEDARR_SLOT_TYPE; + static const size_t TYPE_SLOT = JS_TYPEDOBJ_SLOT_TYPE_DESCR; static const size_t RESERVED_SLOTS = JS_TYPEDOBJ_SLOTS; static const size_t DATA_SLOT = JS_TYPEDOBJ_SLOT_DATA;