Bug 843684 - Bring over self-hosted intrinsics r=till,dvander

This commit is contained in:
Nicholas D. Matsakis 2013-02-19 09:22:35 -05:00
parent 1ccc59cbed
commit de0ccc3cc2
4 changed files with 140 additions and 21 deletions

View File

@ -441,7 +441,7 @@ class IonBuilder : public MIRGenerator
InliningStatus inlineUnsafeSetElement(CallInfo &callInfo); InliningStatus inlineUnsafeSetElement(CallInfo &callInfo);
bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base); bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base);
bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base, int arrayType); bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base, int arrayType);
InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo); InliningStatus inlineShouldForceSequentialOrInParallelSection(CallInfo &callInfo);
InliningStatus inlineNewDenseArray(CallInfo &callInfo); InliningStatus inlineNewDenseArray(CallInfo &callInfo);
InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo); InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo);
InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo); InliningStatus inlineNewDenseArrayForParallelExecution(CallInfo &callInfo);

View File

@ -82,7 +82,25 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
if (native == intrinsic_UnsafeSetElement) if (native == intrinsic_UnsafeSetElement)
return inlineUnsafeSetElement(callInfo); return inlineUnsafeSetElement(callInfo);
if (native == testingFunc_inParallelSection) if (native == testingFunc_inParallelSection)
return inlineForceSequentialOrInParallelSection(callInfo); return inlineShouldForceSequentialOrInParallelSection(callInfo);
if (native == intrinsic_NewDenseArray)
return inlineNewDenseArray(callInfo);
// Self-hosting
if (native == intrinsic_ThrowError)
return inlineThrowError(callInfo);
#ifdef DEBUG
if (native == intrinsic_Dump)
return inlineDump(callInfo);
#endif
// Parallel Array
if (native == intrinsic_UnsafeSetElement)
return inlineUnsafeSetElement(callInfo);
if (native == intrinsic_ShouldForceSequential)
return inlineShouldForceSequentialOrInParallelSection(callInfo);
if (native == testingFunc_inParallelSection)
return inlineShouldForceSequentialOrInParallelSection(callInfo);
if (native == intrinsic_NewDenseArray) if (native == intrinsic_NewDenseArray)
return inlineNewDenseArray(callInfo); return inlineNewDenseArray(callInfo);
@ -1003,7 +1021,7 @@ IonBuilder::inlineUnsafeSetTypedArrayElement(CallInfo &callInfo,
} }
IonBuilder::InliningStatus IonBuilder::InliningStatus
IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo) IonBuilder::inlineShouldForceSequentialOrInParallelSection(CallInfo &callInfo)
{ {
if (callInfo.constructing()) if (callInfo.constructing())
return InliningStatus_NotInlined; return InliningStatus_NotInlined;

View File

@ -2257,8 +2257,7 @@ class ContextAllocPolicy
JSBool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_ForceSequential(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp);
JSBool intrinsic_NewParallelArray(JSContext *cx, unsigned argc, Value *vp);
#ifdef DEBUG #ifdef DEBUG
JSBool intrinsic_Dump(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_Dump(JSContext *cx, unsigned argc, Value *vp);

View File

@ -13,6 +13,7 @@
#include "gc/Marking.h" #include "gc/Marking.h"
#include "vm/ParallelDo.h"
#include "vm/ForkJoin.h" #include "vm/ForkJoin.h"
#include "vm/ThreadPool.h" #include "vm/ThreadPool.h"
@ -170,7 +171,47 @@ intrinsic_DecompileArg(JSContext *cx, unsigned argc, Value *vp)
return true; return true;
} }
/*
* SetScriptHints(fun, flags): Sets various internal hints to the ion
* compiler for use when compiling |fun| or calls to |fun|. Flags
* should be a dictionary object.
*
* The function |fun| should be a self-hosted function (in particular,
* it *must* be a JS function).
*
* Possible flags:
* - |cloneAtCallsite: true| will hint that |fun| should be cloned
* each callsite to improve TI resolution. This is important for
* higher-order functions like |Array.map|.
*/
static JSBool
intrinsic_SetScriptHints(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JS_ASSERT(args.length() >= 2);
JS_ASSERT(args[0].isObject() && args[0].toObject().isFunction());
JS_ASSERT(args[1].isObject());
RootedFunction fun(cx, args[0].toObject().toFunction());
RootedScript funScript(cx, fun->nonLazyScript());
RootedObject flags(cx, &args[1].toObject());
RootedId id(cx);
RootedValue propv(cx);
id = AtomToId(Atomize(cx, "cloneAtCallsite", strlen("cloneAtCallsite")));
if (!JSObject::getGeneric(cx, flags, flags, id, &propv))
return false;
if (ToBoolean(propv))
funScript->shouldCloneAtCallsite = true;
return true;
}
#ifdef DEBUG #ifdef DEBUG
/*
* Dump(val): Dumps a value for debugging, even in parallel mode.
*/
JSBool JSBool
js::intrinsic_Dump(JSContext *cx, unsigned argc, Value *vp) js::intrinsic_Dump(JSContext *cx, unsigned argc, Value *vp)
{ {
@ -183,10 +224,25 @@ js::intrinsic_Dump(JSContext *cx, unsigned argc, Value *vp)
} }
#endif #endif
/*
* ParallelSlices(): Returns the number of parallel slices that will
* be created by ParallelDo().
*/
static JSBool
intrinsic_ParallelSlices(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
args.rval().setInt32(ForkJoinSlices(cx));
return true;
}
/*
* NewDenseArray(length): Allocates and returns a new dense array with
* the given length where all values are initialized to holes.
*/
JSBool JSBool
js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp) js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp)
{ {
// Usage: %NewDenseArray(length)
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
// Check that index is an int32 // Check that index is an int32
@ -223,23 +279,22 @@ js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp)
return false; return false;
} }
/*
* UnsafeSetElement(arr0, idx0, elem0, ..., arrN, idxN, elemN): For
* each set of (arr, idx, elem) arguments that are passed, performs
* the assignment |arr[idx] = elem|. |arr| must be either a dense array
* or a typed array.
*
* If |arr| is a dense array, the index must be an int32 less than the
* initialized length of |arr|. Use |%EnsureDenseResultArrayElements|
* to ensure that the initialized length is long enough.
*
* If |arr| is a typed array, the index must be an int32 less than the
* length of |arr|.
*/
JSBool JSBool
js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp) js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp)
{ {
// Usage: %UnsafeSetElement(arr0, idx0, elem0,
// ...,
// arrN, idxN, elemN)
//
// For each set of |(arr, idx, elem)| arguments that are passed,
// performs the assignment |arr[idx] = elem|. |arr| must be either
// a dense array or a typed array.
//
// If |arr| is a dense array, the index must be an int32 less than the
// initialized length of |arr|. Use |%EnsureDenseResultArrayElements| to
// ensure that the initialized length is long enough.
//
// If |arr| is a typed array, the index must be an int32 less than the
// length of |arr|.
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
if ((args.length() % 3) != 0) { if ((args.length() % 3) != 0) {
@ -276,6 +331,49 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp)
return true; return true;
} }
/*
* ParallelTestsShouldPass(): Returns false if we are running in a
* mode (such as --ion-eager) that is known to cause additional
* bailouts or disqualifications for parallel array tests.
*
* This is needed because the parallel tests generally assert that,
* under normal conditions, they will run without bailouts or
* compilation failures, but this does not hold under "stress-testing"
* conditions like --ion-eager or --no-ti. However, running the tests
* under those conditions HAS exposed bugs and thus we do not wish to
* disable them entirely. Instead, we simply disable the assertions
* that state that no bailouts etc should occur.
*/
static JSBool
intrinsic_ParallelTestsShouldPass(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
#if defined(JS_THREADSAFE) && defined(JS_ION)
args.rval().setBoolean(ion::IsEnabled(cx) &&
!ion::js_IonOptions.eagerCompilation);
#else
args.rval().setBoolean(false);
#endif
return true;
}
/*
* ShouldForceSequential(): Returns true if parallel ops should take
* the sequential fallback path.
*/
JSBool
js::intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
#ifdef JS_THREADSAFE
args.rval().setBoolean(cx->runtime->parallelWarmup ||
InParallelSection());
#else
args.rval().setBoolean(true);
#endif
return true;
}
/** /**
* Returns the default locale as a well-formed, but not necessarily canonicalized, * Returns the default locale as a well-formed, but not necessarily canonicalized,
* BCP-47 language tag. * BCP-47 language tag.
@ -305,12 +403,16 @@ JSFunctionSpec intrinsic_functions[] = {
JS_FN("IsCallable", intrinsic_IsCallable, 1,0), JS_FN("IsCallable", intrinsic_IsCallable, 1,0),
JS_FN("ThrowError", intrinsic_ThrowError, 4,0), JS_FN("ThrowError", intrinsic_ThrowError, 4,0),
JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1,0), JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1,0),
JS_FN("SetScriptHints", intrinsic_SetScriptHints, 2,0),
JS_FN("MakeConstructible", intrinsic_MakeConstructible, 1,0), JS_FN("MakeConstructible", intrinsic_MakeConstructible, 1,0),
JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0), JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0),
JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0), JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0),
JS_FN("NewDenseArray", intrinsic_NewDenseArray, 1,0), JS_FN("ParallelSlices", intrinsic_ParallelSlices, 0,0),
JS_FN("NewDenseArray", intrinsic_NewDenseArray, 1,0),
JS_FN("UnsafeSetElement", intrinsic_UnsafeSetElement, 3,0), JS_FN("UnsafeSetElement", intrinsic_UnsafeSetElement, 3,0),
JS_FN("ShouldForceSequential", intrinsic_ShouldForceSequential, 0,0),
JS_FN("ParallelTestsShouldPass", intrinsic_ParallelTestsShouldPass, 0,0),
#ifdef DEBUG #ifdef DEBUG
JS_FN("Dump", intrinsic_Dump, 1,0), JS_FN("Dump", intrinsic_Dump, 1,0),