зеркало из https://github.com/mozilla/gecko-dev.git
Bug 887016 - Part 8: Add ObjectHasPrototype. r=nbp
This commit is contained in:
Родитель
1b4d64f711
Коммит
877fae40b2
|
@ -0,0 +1,63 @@
|
|||
setJitCompilerOption("ion.warmup.trigger", 4);
|
||||
|
||||
var ObjectHasPrototype = getSelfHostedValue("ObjectHasPrototype");
|
||||
|
||||
var StringProto = String.prototype;
|
||||
var ObjectProto = Object.prototype;
|
||||
|
||||
function testBasic() {
|
||||
var f = function() {
|
||||
assertEq(ObjectHasPrototype(StringProto, ObjectProto), true);
|
||||
};
|
||||
for (var i = 0; i < 40; i++) {
|
||||
f();
|
||||
}
|
||||
}
|
||||
testBasic();
|
||||
|
||||
function testProtoChange(proto) {
|
||||
var f = function(expected) {
|
||||
assertEq(ObjectHasPrototype(StringProto, ObjectProto), expected);
|
||||
};
|
||||
var expected = true;
|
||||
for (var i = 0; i < 120; i++) {
|
||||
f(expected);
|
||||
if (i == 40) {
|
||||
Object.setPrototypeOf(StringProto, proto);
|
||||
expected = false;
|
||||
}
|
||||
if (i == 80) {
|
||||
Object.setPrototypeOf(StringProto, ObjectProto);
|
||||
expected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
testProtoChange(null);
|
||||
// Different singleton
|
||||
testProtoChange(Function.prototype);
|
||||
// native non-singleton
|
||||
testProtoChange(/a/);
|
||||
// non-native non-singleton
|
||||
testProtoChange({});
|
||||
|
||||
var Int32ArrayProto = Int32Array.prototype;
|
||||
var TypedArrayProto = Object.getPrototypeOf(Int32ArrayProto);
|
||||
function testProtoProtoChange(proto) {
|
||||
var f = function() {
|
||||
assertEq(ObjectHasPrototype(Int32ArrayProto, TypedArrayProto), true);
|
||||
};
|
||||
for (var i = 0; i < 120; i++) {
|
||||
f();
|
||||
if (i == 40)
|
||||
Object.setPrototypeOf(TypedArrayProto, proto);
|
||||
if (i == 80)
|
||||
Object.setPrototypeOf(TypedArrayProto, Object);
|
||||
}
|
||||
}
|
||||
testProtoProtoChange(null);
|
||||
// Different singleton
|
||||
testProtoProtoChange(Function.prototype);
|
||||
// native non-singleton
|
||||
testProtoProtoChange(/a/);
|
||||
// non-native non-singleton
|
||||
testProtoProtoChange({});
|
|
@ -106,6 +106,7 @@
|
|||
_(IntrinsicIsConstructing) \
|
||||
_(IntrinsicSubstringKernel) \
|
||||
_(IntrinsicDefineDataProperty) \
|
||||
_(IntrinsicObjectHasPrototype) \
|
||||
\
|
||||
_(IntrinsicIsArrayIterator) \
|
||||
_(IntrinsicIsMapIterator) \
|
||||
|
|
|
@ -922,6 +922,7 @@ class IonBuilder
|
|||
const Class* clasp4 = nullptr);
|
||||
InliningStatus inlineIsConstructing(CallInfo& callInfo);
|
||||
InliningStatus inlineSubstringKernel(CallInfo& callInfo);
|
||||
InliningStatus inlineObjectHasPrototype(CallInfo& callInfo);
|
||||
|
||||
// Testing functions.
|
||||
InliningStatus inlineBailout(CallInfo& callInfo);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jsmath.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "builtin/AtomicsObject.h"
|
||||
|
@ -266,6 +267,8 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
|||
return inlineHasClass(callInfo, &ListIteratorObject::class_);
|
||||
case InlinableNative::IntrinsicDefineDataProperty:
|
||||
return inlineDefineDataProperty(callInfo);
|
||||
case InlinableNative::IntrinsicObjectHasPrototype:
|
||||
return inlineObjectHasPrototype(callInfo);
|
||||
|
||||
// Map intrinsics.
|
||||
case InlinableNative::IntrinsicGetNextMapEntryForIterator:
|
||||
|
@ -1613,6 +1616,58 @@ IonBuilder::inlineStringSplit(CallInfo& callInfo)
|
|||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineObjectHasPrototype(CallInfo& callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 2 || callInfo.constructing()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* objArg = callInfo.getArg(0);
|
||||
MDefinition* protoArg = callInfo.getArg(1);
|
||||
|
||||
if (objArg->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (protoArg->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Inline only when both obj and proto are singleton objects and
|
||||
// obj does not have uncacheable proto and obj.__proto__ is proto.
|
||||
TemporaryTypeSet* objTypes = objArg->resultTypeSet();
|
||||
if (!objTypes || objTypes->unknownObject() || objTypes->getObjectCount() != 1)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
TypeSet::ObjectKey* objKey = objTypes->getObject(0);
|
||||
if (!objKey || !objKey->hasStableClassAndProto(constraints()))
|
||||
return InliningStatus_NotInlined;
|
||||
if (!objKey->isSingleton() || !objKey->singleton()->is<NativeObject>())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
JSObject* obj = &objKey->singleton()->as<NativeObject>();
|
||||
if (obj->hasUncacheableProto())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
JSObject* actualProto = checkNurseryObject(objKey->proto().toObjectOrNull());
|
||||
if (actualProto == nullptr)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
TemporaryTypeSet* protoTypes = protoArg->resultTypeSet();
|
||||
if (!protoTypes || protoTypes->unknownObject() || protoTypes->getObjectCount() != 1)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
TypeSet::ObjectKey* protoKey = protoTypes->getObject(0);
|
||||
if (!protoKey || !protoKey->hasStableClassAndProto(constraints()))
|
||||
return InliningStatus_NotInlined;
|
||||
if (!protoKey->isSingleton() || !protoKey->singleton()->is<NativeObject>())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
JSObject* proto = &protoKey->singleton()->as<NativeObject>();
|
||||
pushConstant(BooleanValue(proto == actualProto));
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineStrCharCodeAt(CallInfo& callInfo)
|
||||
{
|
||||
|
|
|
@ -585,6 +585,22 @@ intrinsic_DefineDataProperty(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_ObjectHasPrototype(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 2);
|
||||
RootedObject obj(cx, &args[0].toObject());
|
||||
RootedObject proto(cx, &args[1].toObject());
|
||||
|
||||
RootedObject actualProto(cx);
|
||||
if (!GetPrototype(cx, obj, &actualProto))
|
||||
return false;
|
||||
|
||||
args.rval().setBoolean(actualProto == proto);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_UnsafeSetReservedSlot(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -2175,6 +2191,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
IntrinsicSubstringKernel),
|
||||
JS_INLINABLE_FN("_DefineDataProperty", intrinsic_DefineDataProperty, 4,0,
|
||||
IntrinsicDefineDataProperty),
|
||||
JS_INLINABLE_FN("ObjectHasPrototype", intrinsic_ObjectHasPrototype, 2,0,
|
||||
IntrinsicObjectHasPrototype),
|
||||
JS_INLINABLE_FN("UnsafeSetReservedSlot", intrinsic_UnsafeSetReservedSlot, 3,0,
|
||||
IntrinsicUnsafeSetReservedSlot),
|
||||
JS_INLINABLE_FN("UnsafeGetReservedSlot", intrinsic_UnsafeGetReservedSlot, 2,0,
|
||||
|
|
Загрузка…
Ссылка в новой задаче