mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 977117 - Enable inlining of the ObjectIsTypeDescr primitive. r=nmatsakis
This commit is contained in:
parent
5b6cc58518
commit
68cd7bf617
@ -880,6 +880,29 @@ IsTypedObjectClass(const Class *class_)
|
||||
class_ == &OpaqueTypedObject::class_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsSimpleTypeDescrClass(const Class* clasp)
|
||||
{
|
||||
return clasp == &ScalarTypeDescr::class_ ||
|
||||
clasp == &ReferenceTypeDescr::class_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsSizedTypeDescrClass(const Class* clasp)
|
||||
{
|
||||
return IsSimpleTypeDescrClass(clasp) ||
|
||||
clasp == &StructTypeDescr::class_ ||
|
||||
clasp == &SizedArrayTypeDescr::class_ ||
|
||||
clasp == &X4TypeDescr::class_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsTypeDescrClass(const Class* clasp)
|
||||
{
|
||||
return IsSizedTypeDescrClass(clasp) ||
|
||||
clasp == &UnsizedArrayTypeDescr::class_;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
JSObject *
|
||||
@ -889,26 +912,21 @@ template <>
|
||||
inline bool
|
||||
JSObject::is<js::SimpleTypeDescr>() const
|
||||
{
|
||||
return is<js::ScalarTypeDescr>() ||
|
||||
is<js::ReferenceTypeDescr>();
|
||||
return IsSimpleTypeDescrClass(getClass());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool
|
||||
JSObject::is<js::SizedTypeDescr>() const
|
||||
{
|
||||
return is<js::SimpleTypeDescr>() ||
|
||||
is<js::StructTypeDescr>() ||
|
||||
is<js::SizedArrayTypeDescr>() ||
|
||||
is<js::X4TypeDescr>();
|
||||
return IsSizedTypeDescrClass(getClass());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool
|
||||
JSObject::is<js::TypeDescr>() const
|
||||
{
|
||||
return is<js::SizedTypeDescr>() ||
|
||||
is<js::UnsizedArrayTypeDescr>();
|
||||
return IsTypeDescrClass(getClass());
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -919,4 +937,3 @@ JSObject::is<js::TypedObject>() const
|
||||
}
|
||||
|
||||
#endif /* builtin_TypedObject_h */
|
||||
|
||||
|
@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Used to verify that the JIT resolves the ObjectIsTypeDescr tests
|
||||
* internal to Type.toSource().
|
||||
*
|
||||
* In this case the argument type is always a type descriptor object
|
||||
* (though not a unique one), so ObjectIsTypeDescr resolves to true
|
||||
* and there should be no exceptions.
|
||||
*
|
||||
* Load this into the js shell with IONFLAGS=logs, then exit and run
|
||||
* iongraph. You're looking for a smallish function within the
|
||||
* "self-hosted" domain. Look for a call to ObjectIsTypeDescr far
|
||||
* down in the graph for pass00, with a call to DescrToSource in a
|
||||
* subsequent block (all of this is at the mercy of the way the code
|
||||
* is currently written).
|
||||
*/
|
||||
|
||||
var T = TypedObject;
|
||||
var ST1 = new T.StructType({x:T.int32});
|
||||
var ST2 = new T.StructType({x:T.float64});
|
||||
|
||||
function check(v) {
|
||||
return v.toSource();
|
||||
}
|
||||
|
||||
function test() {
|
||||
var a = [ ST1, ST2 ];
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
check(a[i%2]);
|
||||
return check(a[0]);
|
||||
}
|
||||
|
||||
print(test());
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Used to verify that the JIT resolves the ObjectIsTypeDescr tests
|
||||
* internal to Type.toSource().
|
||||
*
|
||||
* In this case the argument type is never a type descriptor object,
|
||||
* so ObjectIsTypeDescr resolves to false (and we have to catch
|
||||
* exceptions).
|
||||
*
|
||||
* Load this into the js shell with IONFLAGS=logs, then exit and run
|
||||
* iongraph. You're looking for a smallish function within the
|
||||
* "self-hosted" domain. Look for a call to ObjectIsTypeDescr far
|
||||
* down in the graph for pass00, with a call to DescrToSource in a
|
||||
* subsequent block (all of this is at the mercy of the way the code
|
||||
* is currently written).
|
||||
*/
|
||||
|
||||
var T = TypedObject;
|
||||
var ST = new T.StructType({x:T.int32});
|
||||
|
||||
function check(v) {
|
||||
return v.toSource();
|
||||
}
|
||||
|
||||
function test() {
|
||||
var fake = { toSource: ST.toSource };
|
||||
var a = [ ST, fake ];
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
try { check(a[i%2]); } catch (e) {}
|
||||
try { return check(a[0]); } catch (e) { return "Thrown" }
|
||||
}
|
||||
|
||||
print(test());
|
@ -0,0 +1,38 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Used to verify that the JIT resolves the ObjectIsTypeDescr tests
|
||||
* internal to Type.toSource().
|
||||
*
|
||||
* In this case the argument type is never a type descriptor object
|
||||
* (though not a unique non-type-descriptor), so ObjectIsTypeDescr
|
||||
* resolves to false (and we have to catch exceptions).
|
||||
*
|
||||
* Load this into the js shell with IONFLAGS=logs, then exit and run
|
||||
* iongraph. You're looking for a smallish function within the
|
||||
* "self-hosted" domain. Look for a call to ObjectIsTypeDescr far
|
||||
* down in the graph for pass00, with a call to DescrToSource in a
|
||||
* subsequent block (all of this is at the mercy of the way the code
|
||||
* is currently written).
|
||||
*/
|
||||
|
||||
var T = TypedObject;
|
||||
var ST = new T.StructType({x:T.int32});
|
||||
|
||||
function check(v) {
|
||||
return v.toSource();
|
||||
}
|
||||
|
||||
function test() {
|
||||
var fake1 = { toSource: ST.toSource };
|
||||
var fake2 = []; fake2.toSource = ST.toSource;
|
||||
var a = [ fake1, fake2 ];
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
try { check(a[i%2]); } catch (e) {}
|
||||
try { return check(a[0]); } catch (e) { return "Thrown" }
|
||||
}
|
||||
|
||||
print(test());
|
||||
|
@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Used to verify that the JIT resolves the ObjectIsTypeDescr tests
|
||||
* internal to Type.toSource().
|
||||
*
|
||||
* In this case the argument type is never a type descriptor object,
|
||||
* so ObjectIsTypeDescr resolves to false (and we have to catch
|
||||
* exceptions).
|
||||
*
|
||||
* Load this into the js shell with IONFLAGS=logs, then exit and run
|
||||
* iongraph. You're looking for a smallish function within the
|
||||
* "self-hosted" domain. Look for a call to ObjectIsTypeDescr far
|
||||
* down in the graph for pass00, with a call to DescrToSource in a
|
||||
* subsequent block (all of this is at the mercy of the way the code
|
||||
* is currently written).
|
||||
*/
|
||||
|
||||
var T = TypedObject;
|
||||
var ST = new T.StructType({x:T.int32});
|
||||
|
||||
function check(v) {
|
||||
return v.toSource();
|
||||
}
|
||||
|
||||
function test() {
|
||||
var fake = { toSource: ST.toSource };
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
try { check(fake); } catch (e) {}
|
||||
try { return check(fake); } catch (e) { return "Thrown" }
|
||||
}
|
||||
|
||||
print(test());
|
||||
|
@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Used to verify that the JIT resolves the ObjectIsTypeDescr tests
|
||||
* internal to Type.toSource().
|
||||
*
|
||||
* In this case the argument type is always a type descriptor object,
|
||||
* so ObjectIsTypeDescr resolves to true and there should be no
|
||||
* exceptions.
|
||||
*
|
||||
* Load this into the js shell with IONFLAGS=logs, then exit and run
|
||||
* iongraph. You're looking for a smallish function within the
|
||||
* "self-hosted" domain. Look for a call to ObjectIsTypeDescr far
|
||||
* down in the graph for pass00, with a call to DescrToSource in a
|
||||
* subsequent block (all of this is at the mercy of the way the code
|
||||
* is currently written).
|
||||
*/
|
||||
|
||||
var T = TypedObject;
|
||||
var ST = new T.StructType({x:T.int32});
|
||||
|
||||
function check(v) {
|
||||
return v.toSource();
|
||||
}
|
||||
|
||||
function test() {
|
||||
for ( var i=0 ; i < 1000 ; i++ )
|
||||
check(ST);
|
||||
return check(ST);
|
||||
}
|
||||
|
||||
print(test());
|
||||
|
||||
|
@ -677,6 +677,9 @@ class IonBuilder : public MIRGenerator
|
||||
// ForkJoin intrinsics
|
||||
InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo);
|
||||
|
||||
// TypedObject intrinsics.
|
||||
InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo);
|
||||
|
||||
// Utility intrinsics.
|
||||
InliningStatus inlineIsCallable(CallInfo &callInfo);
|
||||
InliningStatus inlineHaveSameClass(CallInfo &callInfo);
|
||||
|
@ -162,6 +162,8 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
|
||||
return inlineHasClass(callInfo, &TransparentTypedObject::class_);
|
||||
if (native == intrinsic_ObjectIsOpaqueTypedObject)
|
||||
return inlineHasClass(callInfo, &OpaqueTypedObject::class_);
|
||||
if (native == intrinsic_ObjectIsTypeDescr)
|
||||
return inlineObjectIsTypeDescr(callInfo);
|
||||
|
||||
// Testing Functions
|
||||
if (native == testingFunc_inParallelSection)
|
||||
@ -1508,6 +1510,43 @@ IonBuilder::inlineHasClass(CallInfo &callInfo, const Class *clasp)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineObjectIsTypeDescr(CallInfo &callInfo)
|
||||
{
|
||||
if (callInfo.constructing() || callInfo.argc() != 1)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (callInfo.getArg(0)->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
if (getInlineReturnType() != MIRType_Boolean)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// The test is elaborate: in-line only if there is exact
|
||||
// information.
|
||||
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!types)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
bool result = false;
|
||||
switch (types->forAllClasses(IsTypeDescrClass)) {
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case types::TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
result = false;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
result = true;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::MIXED:
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
pushConstant(BooleanValue(result));
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineUnsafeSetReservedSlot(CallInfo &callInfo)
|
||||
{
|
||||
|
@ -1036,6 +1036,7 @@ bool intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
bool intrinsic_ObjectIsTransparentTypedObject(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp);
|
||||
bool intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
class AutoLockForExclusiveAccess
|
||||
{
|
||||
|
@ -1698,6 +1698,37 @@ TemporaryTypeSet::getKnownClass()
|
||||
return clasp;
|
||||
}
|
||||
|
||||
TemporaryTypeSet::ForAllResult
|
||||
TemporaryTypeSet::forAllClasses(bool (*func)(const Class* clasp))
|
||||
{
|
||||
if (unknownObject())
|
||||
return ForAllResult::MIXED;
|
||||
|
||||
unsigned count = getObjectCount();
|
||||
if (count == 0)
|
||||
return ForAllResult::EMPTY;
|
||||
|
||||
bool true_results = false;
|
||||
bool false_results = false;
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
const Class *clasp = getObjectClass(i);
|
||||
if (!clasp)
|
||||
return ForAllResult::MIXED;
|
||||
if (func(clasp)) {
|
||||
true_results = true;
|
||||
if (false_results) return ForAllResult::MIXED;
|
||||
}
|
||||
else {
|
||||
false_results = true;
|
||||
if (true_results) return ForAllResult::MIXED;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(true_results != false_results);
|
||||
|
||||
return true_results ? ForAllResult::ALL_TRUE : ForAllResult::ALL_FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
TemporaryTypeSet::getTypedArrayType()
|
||||
{
|
||||
|
@ -673,6 +673,21 @@ class TemporaryTypeSet : public TypeSet
|
||||
/* Get the class shared by all objects in this set, or nullptr. */
|
||||
const Class *getKnownClass();
|
||||
|
||||
/* Result returned from forAllClasses */
|
||||
enum ForAllResult {
|
||||
EMPTY=1, // Set empty
|
||||
ALL_TRUE, // Set not empty and predicate returned true for all classes
|
||||
ALL_FALSE, // Set not empty and predicate returned false for all classes
|
||||
MIXED, // Set not empty and predicate returned false for some classes
|
||||
// and true for others, or set contains an unknown or non-object
|
||||
// type
|
||||
};
|
||||
|
||||
/* Apply func to the members of the set and return an appropriate result.
|
||||
* The iteration may end early if the result becomes known early.
|
||||
*/
|
||||
ForAllResult forAllClasses(bool (*func)(const Class *clasp));
|
||||
|
||||
/* Get the prototype shared by all objects in this set, or nullptr. */
|
||||
JSObject *getCommonPrototype();
|
||||
|
||||
|
@ -635,6 +635,12 @@ js::intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp)
|
||||
return js::ObjectIsOpaqueTypedObject(cx, argc, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
return js::ObjectIsTypeDescr(cx, argc, vp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default locale as a well-formed, but not necessarily canonicalized,
|
||||
* BCP-47 language tag.
|
||||
@ -712,7 +718,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
JSNativeThreadSafeWrapper<js::SetTypedObjectOffset>,
|
||||
&js::SetTypedObjectOffsetJitInfo, 2, 0),
|
||||
JS_FNINFO("ObjectIsTypeDescr",
|
||||
JSNativeThreadSafeWrapper<js::ObjectIsTypeDescr>,
|
||||
intrinsic_ObjectIsTypeDescr,
|
||||
&js::ObjectIsTypeDescrJitInfo, 5, 0),
|
||||
JS_FNINFO("ObjectIsTransparentTypedObject",
|
||||
intrinsic_ObjectIsTransparentTypedObject,
|
||||
|
Loading…
Reference in New Issue
Block a user