mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to f-t
This commit is contained in:
commit
0190b4669d
@ -22,7 +22,7 @@ AC_DEFUN([MOZ_CONFIG_ICU], [
|
||||
fi
|
||||
MOZ_ICU_VERSION="$version"
|
||||
|
||||
if test -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
|
||||
if test -z "${JS_STANDALONE}" -a -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
|
||||
MOZ_SHARED_ICU=1
|
||||
fi
|
||||
|
||||
|
@ -504,7 +504,7 @@ bool WebGLFramebuffer::CheckColorAttachementNumber(GLenum attachment, const char
|
||||
if (mContext->IsExtensionEnabled(WebGLContext::WEBGL_draw_buffers))
|
||||
{
|
||||
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
||||
attachment > GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
|
||||
attachment >= GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
|
||||
{
|
||||
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
|
||||
return false;
|
||||
|
@ -614,6 +614,8 @@ private:
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
||||
{
|
||||
mInput->PickerClosed();
|
||||
|
||||
if (aResult == nsIFilePicker::returnCancel) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -796,6 +798,8 @@ nsColorPickerShownCallback::Done(const nsAString& aColor)
|
||||
*/
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
mInput->PickerClosed();
|
||||
|
||||
if (!aColor.IsEmpty()) {
|
||||
UpdateInternal(aColor, false);
|
||||
}
|
||||
@ -839,6 +843,11 @@ HTMLInputElement::IsPopupBlocked() const
|
||||
nsresult
|
||||
HTMLInputElement::InitColorPicker()
|
||||
{
|
||||
if (mPickerRunning) {
|
||||
NS_WARNING("Just one nsIColorPicker is allowed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = OwnerDoc();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = doc->GetWindow();
|
||||
@ -869,12 +878,22 @@ HTMLInputElement::InitColorPicker()
|
||||
nsCOMPtr<nsIColorPickerShownCallback> callback =
|
||||
new nsColorPickerShownCallback(this, colorPicker);
|
||||
|
||||
return colorPicker->Open(callback);
|
||||
rv = colorPicker->Open(callback);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mPickerRunning = true;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLInputElement::InitFilePicker(FilePickerType aType)
|
||||
{
|
||||
if (mPickerRunning) {
|
||||
NS_WARNING("Just one nsIFilePicker is allowed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get parent nsPIDOMWindow object.
|
||||
nsCOMPtr<nsIDocument> doc = OwnerDoc();
|
||||
|
||||
@ -955,10 +974,16 @@ HTMLInputElement::InitFilePicker(FilePickerType aType)
|
||||
}
|
||||
}
|
||||
|
||||
return filePicker->Open(callback);
|
||||
rv = filePicker->Open(callback);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mPickerRunning = true;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
HTMLInputElement::gUploadLastDir->FetchDirectoryAndDisplayPicker(doc, filePicker, callback);
|
||||
mPickerRunning = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1094,6 +1119,8 @@ HTMLInputElement::HTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
, mIsDraggingRange(false)
|
||||
, mProgressTimerIsActive(false)
|
||||
, mNumberControlSpinnerIsSpinning(false)
|
||||
, mNumberControlSpinnerSpinsUp(false)
|
||||
, mPickerRunning(false)
|
||||
{
|
||||
// We are in a type=text so we now we currenty need a nsTextEditorState.
|
||||
mInputData.mState = new nsTextEditorState(this);
|
||||
@ -7178,6 +7205,12 @@ HTMLInputElement::UpdateHasRange()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::PickerClosed()
|
||||
{
|
||||
mPickerRunning = false;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
HTMLInputElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
|
@ -203,6 +203,9 @@ public:
|
||||
void SetFiles(const nsTArray<nsCOMPtr<nsIDOMFile> >& aFiles, bool aSetValueChanged);
|
||||
void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
|
||||
|
||||
// Called when a nsIFilePicker or a nsIColorPicker terminate.
|
||||
void PickerClosed();
|
||||
|
||||
void SetCheckedChangedInternal(bool aCheckedChanged);
|
||||
bool GetCheckedChanged() const {
|
||||
return mCheckedChanged;
|
||||
@ -1267,6 +1270,7 @@ protected:
|
||||
bool mProgressTimerIsActive : 1;
|
||||
bool mNumberControlSpinnerIsSpinning : 1;
|
||||
bool mNumberControlSpinnerSpinsUp : 1;
|
||||
bool mPickerRunning : 1;
|
||||
|
||||
private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
|
@ -21,6 +21,7 @@ using namespace mozilla::gfx;
|
||||
using namespace mozilla::layers;
|
||||
using ::testing::_;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::AtLeast;
|
||||
|
||||
class MockContentController : public GeckoContentController {
|
||||
public:
|
||||
@ -169,7 +170,7 @@ TEST(AsyncPanZoomController, Pinch) {
|
||||
apzc->SetFrameMetrics(fm);
|
||||
// the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
|
||||
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(2);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||
|
||||
ApzcPinch(apzc, 250, 300, 1.25);
|
||||
@ -209,7 +210,7 @@ TEST(AsyncPanZoomController, Overzoom) {
|
||||
apzc->SetFrameMetrics(fm);
|
||||
// the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
|
||||
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(1);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||
|
||||
ApzcPinch(apzc, 50, 50, 0.5);
|
||||
@ -353,7 +354,7 @@ TEST(AsyncPanZoomController, Pan) {
|
||||
apzc->SetFrameMetrics(TestFrameMetrics());
|
||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(4);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||
|
||||
int time = 0;
|
||||
@ -386,7 +387,7 @@ TEST(AsyncPanZoomController, Fling) {
|
||||
apzc->SetFrameMetrics(TestFrameMetrics());
|
||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(2);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||
|
||||
int time = 0;
|
||||
@ -416,7 +417,7 @@ TEST(AsyncPanZoomController, OverScrollPanning) {
|
||||
apzc->SetFrameMetrics(TestFrameMetrics());
|
||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(4);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||
|
||||
// Pan sufficiently to hit overscroll behavior
|
||||
@ -659,7 +660,7 @@ TEST(APZCTreeManager, HitTesting2) {
|
||||
int time = 0;
|
||||
// Silence GMock warnings about "uninteresting mock function calls".
|
||||
EXPECT_CALL(*mcc, PostDelayedTask(_,_)).Times(1);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(2);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||
ApzcPan(apzcroot, manager, time, 100, 50);
|
||||
|
||||
|
@ -1523,6 +1523,7 @@ class HashTable : private AllocPolicy
|
||||
p.mutationCount = mutationCount;
|
||||
{
|
||||
mozilla::ReentrancyGuard g(*this);
|
||||
JS_ASSERT(prepareHash(l) == p.keyHash); // l has not been destroyed
|
||||
p.entry_ = &lookup(l, p.keyHash, sCollisionBit);
|
||||
}
|
||||
return p.found() || add(p, mozilla::Forward<U>(u));
|
||||
|
@ -125,6 +125,7 @@ include $(topsrcdir)/config/config.mk
|
||||
# Ensure that this happens before including rules.mk
|
||||
ifdef ENABLE_INTL_API
|
||||
ifndef MOZ_NATIVE_ICU
|
||||
ifdef MOZ_SHARED_ICU
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
# Library names: On Windows, ICU uses modified library names for static
|
||||
# and debug libraries.
|
||||
@ -156,6 +157,7 @@ ifdef ICU_FILES
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -22,7 +22,7 @@ AC_DEFUN([MOZ_CONFIG_ICU], [
|
||||
fi
|
||||
MOZ_ICU_VERSION="$version"
|
||||
|
||||
if test -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
|
||||
if test -z "${JS_STANDALONE}" -a -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
|
||||
MOZ_SHARED_ICU=1
|
||||
fi
|
||||
|
||||
|
@ -1119,11 +1119,11 @@ SetJitCompilerOption(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
SetIonAssertGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
|
||||
SetIonCheckGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
#ifdef JS_ION
|
||||
jit::js_IonOptions.assertGraphConsistency = ToBoolean(args.get(0));
|
||||
jit::js_IonOptions.checkGraphConsistency = ToBoolean(args.get(0));
|
||||
#endif
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
@ -1577,8 +1577,8 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||
"setCompilerOption(<option>, <number>)",
|
||||
" Set a compiler option indexed in JSCompileOption enum to a number.\n"),
|
||||
|
||||
JS_FN_HELP("setIonAssertGraphCoherency", SetIonAssertGraphCoherency, 1, 0,
|
||||
"setIonAssertGraphCoherency(bool)",
|
||||
JS_FN_HELP("setIonCheckGraphCoherency", SetIonCheckGraphCoherency, 1, 0,
|
||||
"setIonCheckGraphCoherency(bool)",
|
||||
" Set whether Ion should perform graph consistency (DEBUG-only) assertions. These assertions\n"
|
||||
" are valuable and should be generally enabled, however they can be very expensive for large\n"
|
||||
" (asm.js) programs."),
|
||||
|
@ -1135,7 +1135,6 @@ if test "$GNU_CC"; then
|
||||
#
|
||||
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement"
|
||||
MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare)
|
||||
|
||||
@ -4213,7 +4212,7 @@ if test -n "$ENABLE_INTL_API"; then
|
||||
case "$OS_TARGET" in
|
||||
WINNT)
|
||||
ICU_LIB_NAMES="icuin icuuc icudt"
|
||||
if test "$DISABLE_SHARED_JS" != "1"; then
|
||||
if test -n "$MOZ_SHARED_ICU"; then
|
||||
DBG_SUFFIX=
|
||||
if test -n "$MOZ_DEBUG"; then
|
||||
DBG_SUFFIX=d
|
||||
@ -4223,20 +4222,20 @@ if test -n "$ENABLE_INTL_API"; then
|
||||
;;
|
||||
Darwin)
|
||||
ICU_LIB_NAMES="icui18n icuuc icudata"
|
||||
if test "$DISABLE_SHARED_JS" != "1"; then
|
||||
if test -n "$MOZ_SHARED_ICU"; then
|
||||
MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib/$(DLL_PREFIX)$(lib).$(MOZ_ICU_VERSION)$(DLL_SUFFIX))'
|
||||
fi
|
||||
;;
|
||||
Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
|
||||
ICU_LIB_NAMES="icui18n icuuc icudata"
|
||||
if test "$DISABLE_SHARED_JS" != "1"; then
|
||||
if test -n "$MOZ_SHARED_ICU"; then
|
||||
MOZ_ICU_LIBS='$(foreach lib,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib/$(DLL_PREFIX)$(lib)$(DLL_SUFFIX).$(MOZ_ICU_VERSION))'
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
|
||||
esac
|
||||
if test "$DISABLE_SHARED_JS" = "1"; then
|
||||
if test -z "$MOZ_SHARED_ICU"; then
|
||||
MOZ_ICU_LIBS='$(call EXPAND_LIBNAME_PATH,$(ICU_LIB_NAMES),$(DEPTH)/intl/icu/target/lib)'
|
||||
fi
|
||||
fi
|
||||
@ -4251,7 +4250,7 @@ AC_SUBST(MOZ_NATIVE_ICU)
|
||||
dnl Settings for ICU
|
||||
if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
|
||||
dnl We build ICU as a static library for non-shared js builds and as a shared library for shared js builds.
|
||||
if test "$DISABLE_SHARED_JS" = "1"; then
|
||||
if test -z "$MOZ_SHARED_ICU"; then
|
||||
AC_DEFINE(U_STATIC_IMPLEMENTATION)
|
||||
else
|
||||
AC_DEFINE(U_COMBINED_IMPLEMENTATION)
|
||||
@ -4347,7 +4346,7 @@ if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
|
||||
ICU_TARGET_OPT="--build=$target --host=$target"
|
||||
fi
|
||||
|
||||
if test "$DISABLE_SHARED_JS" = "1"; then
|
||||
if test -z "$MOZ_SHARED_ICU"; then
|
||||
# To reduce library size, use static linking
|
||||
ICU_LINK_OPTS="--enable-static --disable-shared"
|
||||
else
|
||||
|
@ -678,13 +678,20 @@ static bool
|
||||
PushBlockScopeBCE(BytecodeEmitter *bce, StmtInfoBCE *stmt, ObjectBox *objbox,
|
||||
ptrdiff_t top)
|
||||
{
|
||||
uint32_t parent = UINT32_MAX;
|
||||
if (bce->blockChain) {
|
||||
StmtInfoBCE *stmt = bce->topScopeStmt;
|
||||
for (; stmt->blockObj != bce->blockChain; stmt = stmt->down) {}
|
||||
parent = stmt->blockScopeIndex;
|
||||
}
|
||||
|
||||
StaticBlockObject &blockObj = objbox->object->as<StaticBlockObject>();
|
||||
|
||||
PushStatementBCE(bce, stmt, STMT_BLOCK, top);
|
||||
|
||||
unsigned scopeObjectIndex = bce->objectList.add(objbox);
|
||||
stmt->blockScopeIndex = bce->blockScopeList.length();
|
||||
if (!bce->blockScopeList.append(scopeObjectIndex, bce->offset()))
|
||||
if (!bce->blockScopeList.append(scopeObjectIndex, bce->offset(), parent))
|
||||
return false;
|
||||
|
||||
blockObj.initEnclosingStaticScope(EnclosingStaticScope(bce));
|
||||
@ -814,11 +821,7 @@ EmitAliasedVarOp(ExclusiveContext *cx, JSOp op, ScopeCoordinate sc, BytecodeEmit
|
||||
{
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_SCOPECOORD);
|
||||
|
||||
uint32_t maybeBlockIndex = UINT32_MAX;
|
||||
if (bce->blockChain)
|
||||
maybeBlockIndex = bce->objectList.indexOf(bce->blockChain);
|
||||
|
||||
unsigned n = 2 * sizeof(uint16_t) + sizeof(uint32_t);
|
||||
unsigned n = 2 * sizeof(uint16_t);
|
||||
JS_ASSERT(int(n) + 1 /* op */ == js_CodeSpec[op].length);
|
||||
|
||||
ptrdiff_t off = EmitN(cx, bce, op, n);
|
||||
@ -830,7 +833,6 @@ EmitAliasedVarOp(ExclusiveContext *cx, JSOp op, ScopeCoordinate sc, BytecodeEmit
|
||||
pc += sizeof(uint16_t);
|
||||
SET_UINT16(pc, sc.slot);
|
||||
pc += sizeof(uint16_t);
|
||||
SET_UINT32_INDEX(pc, maybeBlockIndex);
|
||||
CheckTypeSet(cx, bce, op);
|
||||
return true;
|
||||
}
|
||||
@ -6879,13 +6881,14 @@ CGTryNoteList::finish(TryNoteArray *array)
|
||||
}
|
||||
|
||||
bool
|
||||
CGBlockScopeList::append(uint32_t scopeObject, uint32_t offset)
|
||||
CGBlockScopeList::append(uint32_t scopeObject, uint32_t offset, uint32_t parent)
|
||||
{
|
||||
BlockScopeNote note;
|
||||
mozilla::PodZero(¬e);
|
||||
|
||||
note.index = scopeObject;
|
||||
note.start = offset;
|
||||
note.parent = parent;
|
||||
|
||||
return list.append(note);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ struct CGBlockScopeList {
|
||||
Vector<BlockScopeNote> list;
|
||||
CGBlockScopeList(ExclusiveContext *cx) : list(cx) {}
|
||||
|
||||
bool append(uint32_t scopeObject, uint32_t offset);
|
||||
bool append(uint32_t scopeObject, uint32_t offset, uint32_t parent);
|
||||
void recordEnd(uint32_t index, uint32_t offset);
|
||||
size_t length() const { return list.length(); }
|
||||
void finish(BlockScopeArray *array);
|
||||
|
@ -9,9 +9,9 @@ if (!isAsmJSCompilationAvailable())
|
||||
// bullet.js and not the nestedShell() call, so try first commenting out
|
||||
// nestedShell() (and the loadedFromCache assertion) to see if the error
|
||||
// reproduces.
|
||||
var code = "setIonAssertGraphCoherency(false); load('" + libdir + "bullet.js'); runBullet()";
|
||||
var code = "setIonCheckGraphCoherency(false); load('" + libdir + "bullet.js'); runBullet()";
|
||||
nestedShell("--js-cache", "--execute=" + code);
|
||||
setIonAssertGraphCoherency(false);
|
||||
setIonCheckGraphCoherency(false);
|
||||
load(libdir + 'bullet.js');
|
||||
var results = runBullet();
|
||||
assertEq(results.asmJSValidated, true);
|
||||
|
@ -2,7 +2,7 @@ load(libdir + "asm.js");
|
||||
|
||||
// constants
|
||||
var buf = new ArrayBuffer(4096);
|
||||
setIonAssertGraphCoherency(false);
|
||||
setIonCheckGraphCoherency(false);
|
||||
|
||||
// An unshifted literal constant byte index in the range 0 to 2^31-1 inclusive should give a link failure.
|
||||
assertAsmLinkFail(asmCompile('glob', 'imp', 'b', USE_ASM + 'var arr=new glob.Int8Array(b); function f() {return arr[0x7fffffff]|0 } return f'), this, null, buf);
|
||||
|
@ -3,7 +3,7 @@ setDebug(true);
|
||||
x = "notset";
|
||||
function main() {
|
||||
/* The JSOP_STOP in main. */
|
||||
a = { valueOf: function () { trap(main, 95, "success()"); } };
|
||||
a = { valueOf: function () { trap(main, 91, "success()"); } };
|
||||
b = "";
|
||||
eval();
|
||||
a + b;
|
||||
|
@ -5507,7 +5507,7 @@ AssertStackAlignment(MacroAssembler &masm)
|
||||
Label ok;
|
||||
JS_ASSERT(IsPowerOfTwo(StackAlignment));
|
||||
masm.branchTestPtr(Assembler::Zero, StackPointer, Imm32(StackAlignment - 1), &ok);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Stack should be aligned.");
|
||||
masm.bind(&ok);
|
||||
#endif
|
||||
}
|
||||
@ -5962,7 +5962,6 @@ GenerateOOLConvert(ModuleCompiler &m, RetType retType, Label *throwLabel)
|
||||
// passed to this FFI call.
|
||||
unsigned arraySize = sizeof(Value);
|
||||
unsigned stackDec = StackDecrementForCall(masm, callArgTypes, arraySize);
|
||||
masm.setFramePushed(0);
|
||||
masm.reserveStack(stackDec);
|
||||
|
||||
// Store value
|
||||
@ -5996,6 +5995,7 @@ GenerateOOLConvert(ModuleCompiler &m, RetType retType, Label *throwLabel)
|
||||
JS_ASSERT(i.done());
|
||||
|
||||
// Call
|
||||
AssertStackAlignment(masm);
|
||||
switch (retType.which()) {
|
||||
case RetType::Signed:
|
||||
masm.call(AsmJSImm_CoerceInPlace_ToInt32);
|
||||
@ -6138,6 +6138,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
||||
masm.branchTestMagic(Assembler::Equal, JSReturnOperand, throwLabel);
|
||||
#endif
|
||||
|
||||
uint32_t oolConvertFramePushed = masm.framePushed();
|
||||
switch (exit.sig().retType().which()) {
|
||||
case RetType::Void:
|
||||
break;
|
||||
@ -6160,13 +6161,15 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
||||
// oolConvert
|
||||
if (oolConvert.used()) {
|
||||
masm.bind(&oolConvert);
|
||||
masm.setFramePushed(oolConvertFramePushed);
|
||||
GenerateOOLConvert(m, exit.sig().retType(), throwLabel);
|
||||
masm.setFramePushed(0);
|
||||
masm.jump(&done);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
masm.bind(&ionFailed);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("AsmJS to IonMonkey call failed.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2365,6 +2365,10 @@ BaselineCompiler::emit_JSOP_CALLARG()
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_SETARG()
|
||||
{
|
||||
// Ionmonkey can't inline functions with SETARG with magic arguments.
|
||||
if (!script->argsObjAliasesFormals() && script->argumentsAliasesFormals())
|
||||
script->uninlineable = true;
|
||||
|
||||
modifiesArguments_ = true;
|
||||
|
||||
uint32_t arg = GET_SLOTNO(pc);
|
||||
@ -2504,6 +2508,8 @@ BaselineCompiler::emit_JSOP_THROW()
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_TRY()
|
||||
{
|
||||
// Ionmonkey can't inline function with JSOP_TRY.
|
||||
script->uninlineable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1095,7 +1095,7 @@ ICProfiler_PushFunction::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
Label spsEnabled;
|
||||
uint32_t *enabledAddr = cx->runtime()->spsProfiler.addressOfEnabled();
|
||||
masm.branch32(Assembler::NotEqual, AbsoluteAddress(enabledAddr), Imm32(0), &spsEnabled);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Profiling should have been enabled.");
|
||||
masm.bind(&spsEnabled);
|
||||
#endif
|
||||
|
||||
@ -5133,7 +5133,7 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
if (cx->runtime()->jitSupportsFloatingPoint)
|
||||
masm.convertInt32ValueToDouble(valueAddr, regs.getAny(), &dontConvertDoubles);
|
||||
else
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("There shouldn't be double arrays when there is no FP support.");
|
||||
masm.bind(&dontConvertDoubles);
|
||||
|
||||
// Don't overwrite R0 becuase |obj| might overlap with it, and it's needed
|
||||
@ -5321,7 +5321,7 @@ ICSetElemDenseAddCompiler::generateStubCode(MacroAssembler &masm)
|
||||
if (cx->runtime()->jitSupportsFloatingPoint)
|
||||
masm.convertInt32ValueToDouble(valueAddr, regs.getAny(), &dontConvertDoubles);
|
||||
else
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("There shouldn't be double arrays when there is no FP support.");
|
||||
masm.bind(&dontConvertDoubles);
|
||||
|
||||
// Write the value. No need for pre-barrier since we're not overwriting an old value.
|
||||
@ -8284,7 +8284,7 @@ ICCall_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.moveValue(R1, R0);
|
||||
#ifdef DEBUG
|
||||
masm.branchTestObject(Assembler::Equal, JSReturnOperand, &skipThisReplace);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Failed to return object in constructing call.");
|
||||
#endif
|
||||
masm.bind(&skipThisReplace);
|
||||
|
||||
@ -8393,7 +8393,7 @@ ICCallScriptedCompiler::generateStubCode(MacroAssembler &masm)
|
||||
#ifdef DEBUG
|
||||
Label createdThisIsObject;
|
||||
masm.branchTestObject(Assembler::Equal, JSReturnOperand, &createdThisIsObject);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("The return of CreateThis must be an object.");
|
||||
masm.bind(&createdThisIsObject);
|
||||
#endif
|
||||
|
||||
@ -8534,7 +8534,7 @@ ICCallScriptedCompiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.loadValue(reloadThisSlot, JSReturnOperand);
|
||||
#ifdef DEBUG
|
||||
masm.branchTestObject(Assembler::Equal, JSReturnOperand, &skipThisReplace);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Return of constructing call should be an object.");
|
||||
#endif
|
||||
masm.bind(&skipThisReplace);
|
||||
}
|
||||
|
@ -2498,7 +2498,7 @@ CodeGenerator::generateArgumentsChecks(bool bailout)
|
||||
Label success;
|
||||
masm.jump(&success);
|
||||
masm.bind(&miss);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Argument check fail.");
|
||||
masm.bind(&success);
|
||||
}
|
||||
}
|
||||
@ -3672,7 +3672,7 @@ CodeGenerator::visitGetArgumentsObjectArg(LGetArgumentsObjectArg *lir)
|
||||
#ifdef DEBUG
|
||||
Label success;
|
||||
masm.branchTestMagic(Assembler::NotEqual, out, &success);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Result from ArgumentObject shouldn't be MIRType_Magic.");
|
||||
masm.bind(&success);
|
||||
#endif
|
||||
return true;
|
||||
@ -3691,7 +3691,7 @@ CodeGenerator::visitSetArgumentsObjectArg(LSetArgumentsObjectArg *lir)
|
||||
#ifdef DEBUG
|
||||
Label success;
|
||||
masm.branchTestMagic(Assembler::NotEqual, argAddr, &success);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Result in ArgumentObject shouldn't be MIRType_Magic.");
|
||||
masm.bind(&success);
|
||||
#endif
|
||||
masm.storeValue(value, argAddr);
|
||||
@ -4520,7 +4520,7 @@ CopyStringChars(MacroAssembler &masm, Register to, Register from, Register len,
|
||||
#ifdef DEBUG
|
||||
Label ok;
|
||||
masm.branch32(Assembler::GreaterThan, len, Imm32(0), &ok);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Length should be greater than 0.");
|
||||
masm.bind(&ok);
|
||||
#endif
|
||||
|
||||
@ -5918,6 +5918,20 @@ CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
|
||||
if (sps_.enabled())
|
||||
ionScript->setHasSPSInstrumentation();
|
||||
|
||||
// We finished the new IonScript. Invalidate the current active IonScript,
|
||||
// so we can replace it with this new (probably higher optimized) version.
|
||||
if (HasIonScript(script, executionMode)) {
|
||||
JS_ASSERT(GetIonScript(script, executionMode)->isRecompiling());
|
||||
// Do a normal invalidate, except don't cancel offThread compilations,
|
||||
// since that will cancel this compilation too.
|
||||
if (!Invalidate(cx, script, SequentialExecution,
|
||||
/* resetUses */ false, /* cancelOffThread*/ false))
|
||||
{
|
||||
js_free(ionScript);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetIonScript(script, executionMode, ionScript);
|
||||
|
||||
// In parallel execution mode, when we first compile a script, we
|
||||
@ -7688,7 +7702,7 @@ CodeGenerator::visitAsmJSCall(LAsmJSCall *ins)
|
||||
Label ok;
|
||||
JS_ASSERT(IsPowerOfTwo(StackAlignment));
|
||||
masm.branchTestPtr(Assembler::Zero, StackPointer, Imm32(StackAlignment - 1), &ok);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Stack should be aligned.");
|
||||
masm.bind(&ok);
|
||||
#endif
|
||||
|
||||
@ -7767,7 +7781,7 @@ CodeGenerator::emitAssertRangeI(const Range *r, Register input)
|
||||
if (r->hasInt32LowerBound() && r->lower() > INT32_MIN) {
|
||||
Label success;
|
||||
masm.branch32(Assembler::GreaterThanOrEqual, input, Imm32(r->lower()), &success);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Integer input should be equal or higher than Lowerbound.");
|
||||
masm.bind(&success);
|
||||
}
|
||||
|
||||
@ -7775,7 +7789,7 @@ CodeGenerator::emitAssertRangeI(const Range *r, Register input)
|
||||
if (r->hasInt32UpperBound() && r->upper() < INT32_MAX) {
|
||||
Label success;
|
||||
masm.branch32(Assembler::LessThanOrEqual, input, Imm32(r->upper()), &success);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Integer input should be lower or equal than Upperbound.");
|
||||
masm.bind(&success);
|
||||
}
|
||||
|
||||
@ -7796,7 +7810,7 @@ CodeGenerator::emitAssertRangeD(const Range *r, FloatRegister input, FloatRegist
|
||||
if (r->canBeNaN())
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &success);
|
||||
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, input, temp, &success);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Double input should be equal or higher than Lowerbound.");
|
||||
masm.bind(&success);
|
||||
}
|
||||
// Check the upper bound.
|
||||
@ -7806,7 +7820,7 @@ CodeGenerator::emitAssertRangeD(const Range *r, FloatRegister input, FloatRegist
|
||||
if (r->canBeNaN())
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &success);
|
||||
masm.branchDouble(Assembler::DoubleLessThanOrEqual, input, temp, &success);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Double input should be lower or equal than Upperbound.");
|
||||
masm.bind(&success);
|
||||
}
|
||||
|
||||
@ -7819,20 +7833,20 @@ CodeGenerator::emitAssertRangeD(const Range *r, FloatRegister input, FloatRegist
|
||||
masm.loadConstantDouble(pow(2.0, r->exponent() + 1), temp);
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &exponentLoOk);
|
||||
masm.branchDouble(Assembler::DoubleLessThanOrEqual, input, temp, &exponentLoOk);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Check for exponent failed.");
|
||||
masm.bind(&exponentLoOk);
|
||||
|
||||
Label exponentHiOk;
|
||||
masm.loadConstantDouble(-pow(2.0, r->exponent() + 1), temp);
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &exponentHiOk);
|
||||
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, input, temp, &exponentHiOk);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Check for exponent failed.");
|
||||
masm.bind(&exponentHiOk);
|
||||
} else if (!r->hasInt32Bounds() && !r->canBeNaN()) {
|
||||
// If we think the value can't be NaN, check that it isn't.
|
||||
Label notnan;
|
||||
masm.branchDouble(Assembler::DoubleOrdered, input, input, ¬nan);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Input shouldn't be NaN.");
|
||||
masm.bind(¬nan);
|
||||
|
||||
// If we think the value also can't be an infinity, check that it isn't.
|
||||
@ -7840,13 +7854,13 @@ CodeGenerator::emitAssertRangeD(const Range *r, FloatRegister input, FloatRegist
|
||||
Label notposinf;
|
||||
masm.loadConstantDouble(PositiveInfinity(), temp);
|
||||
masm.branchDouble(Assembler::DoubleLessThan, input, temp, ¬posinf);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Input shouldn't be +Inf.");
|
||||
masm.bind(¬posinf);
|
||||
|
||||
Label notneginf;
|
||||
masm.loadConstantDouble(NegativeInfinity(), temp);
|
||||
masm.branchDouble(Assembler::DoubleGreaterThan, input, temp, ¬neginf);
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Input shouldn't be -Inf.");
|
||||
masm.bind(¬neginf);
|
||||
}
|
||||
}
|
||||
@ -7915,7 +7929,7 @@ CodeGenerator::visitAssertRangeV(LAssertRangeV *ins)
|
||||
masm.bind(&isNotDouble);
|
||||
}
|
||||
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Incorrect range for Value.");
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
|
@ -518,6 +518,10 @@ jit::FinishOffThreadBuilder(IonBuilder *builder)
|
||||
{
|
||||
ExecutionMode executionMode = builder->info().executionMode();
|
||||
|
||||
// Clear the recompiling flag if it would have failed.
|
||||
if (builder->script()->hasIonScript())
|
||||
builder->script()->ionScript()->clearRecompiling();
|
||||
|
||||
// Clean up if compilation did not succeed.
|
||||
if (CompilingOffThread(builder->script(), executionMode))
|
||||
SetIonScript(builder->script(), executionMode, nullptr);
|
||||
@ -722,6 +726,7 @@ IonScript::IonScript()
|
||||
numBailouts_(0),
|
||||
hasUncompiledCallTarget_(false),
|
||||
hasSPSInstrumentation_(false),
|
||||
recompiling_(false),
|
||||
runtimeData_(0),
|
||||
runtimeSize_(0),
|
||||
cacheIndex_(0),
|
||||
@ -1600,7 +1605,7 @@ TrackPropertiesForSingletonScopes(JSContext *cx, JSScript *script, BaselineFrame
|
||||
static AbortReason
|
||||
IonCompile(JSContext *cx, JSScript *script,
|
||||
BaselineFrame *baselineFrame, jsbytecode *osrPc, bool constructing,
|
||||
ExecutionMode executionMode)
|
||||
ExecutionMode executionMode, bool recompile)
|
||||
{
|
||||
#if JS_TRACE_LOGGING
|
||||
AutoTraceLog logger(TraceLogging::defaultLogger(),
|
||||
@ -1608,7 +1613,6 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
TraceLogging::ION_COMPILE_STOP,
|
||||
script);
|
||||
#endif
|
||||
|
||||
TrackPropertiesForSingletonScopes(cx, script, baselineFrame);
|
||||
|
||||
LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
|
||||
@ -1663,7 +1667,7 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
if (!builder)
|
||||
return AbortReason_Alloc;
|
||||
|
||||
JS_ASSERT(!GetIonScript(builder->script(), executionMode));
|
||||
JS_ASSERT(recompile == HasIonScript(builder->script(), executionMode));
|
||||
JS_ASSERT(CanIonCompile(builder->script(), executionMode));
|
||||
|
||||
RootedScript builderScript(cx, builder->script());
|
||||
@ -1693,7 +1697,12 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
|
||||
// If possible, compile the script off thread.
|
||||
if (OffThreadCompilationAvailable(cx)) {
|
||||
if (recompile) {
|
||||
JS_ASSERT(executionMode == SequentialExecution);
|
||||
builderScript->ionScript()->setRecompiling();
|
||||
} else {
|
||||
SetIonScript(builder->script(), executionMode, ION_COMPILING_SCRIPT);
|
||||
}
|
||||
|
||||
if (!StartOffThreadIonCompile(cx, builder)) {
|
||||
IonSpew(IonSpew_Abort, "Unable to start off-thread ion compilation.");
|
||||
@ -1862,6 +1871,8 @@ Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode
|
||||
return status;
|
||||
}
|
||||
|
||||
bool recompile = false;
|
||||
|
||||
IonScript *scriptIon = GetIonScript(script, executionMode);
|
||||
if (scriptIon) {
|
||||
if (!scriptIon->method())
|
||||
@ -1876,7 +1887,8 @@ Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode
|
||||
return Method_Skipped;
|
||||
}
|
||||
|
||||
AbortReason reason = IonCompile(cx, script, osrFrame, osrPc, constructing, executionMode);
|
||||
AbortReason reason = IonCompile(cx, script, osrFrame, osrPc, constructing, executionMode,
|
||||
recompile);
|
||||
if (reason == AbortReason_Error)
|
||||
return Method_Error;
|
||||
|
||||
@ -2057,6 +2069,25 @@ jit::CompileFunctionForBaseline(JSContext *cx, HandleScript script, BaselineFram
|
||||
return Method_Compiled;
|
||||
}
|
||||
|
||||
MethodStatus
|
||||
jit::Recompile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc,
|
||||
bool constructing)
|
||||
{
|
||||
JS_ASSERT(script->hasIonScript());
|
||||
if (script->ionScript()->isRecompiling())
|
||||
return Method_Compiled;
|
||||
|
||||
MethodStatus status =
|
||||
Compile(cx, script, osrFrame, osrPc, constructing, SequentialExecution);
|
||||
if (status != Method_Compiled) {
|
||||
if (status == Method_CantCompile)
|
||||
ForbidCompilation(cx, script);
|
||||
return status;
|
||||
}
|
||||
|
||||
return Method_Compiled;
|
||||
}
|
||||
|
||||
MethodStatus
|
||||
jit::CanEnterInParallel(JSContext *cx, HandleScript script)
|
||||
{
|
||||
@ -2428,7 +2459,8 @@ jit::InvalidateAll(FreeOp *fop, Zone *zone)
|
||||
|
||||
void
|
||||
jit::Invalidate(types::TypeCompartment &types, FreeOp *fop,
|
||||
const Vector<types::RecompileInfo> &invalid, bool resetUses)
|
||||
const Vector<types::RecompileInfo> &invalid, bool resetUses,
|
||||
bool cancelOffThread)
|
||||
{
|
||||
IonSpew(IonSpew_Invalidate, "Start invalidation.");
|
||||
AutoFlushCache afc ("Invalidate", fop->runtime()->jitRuntime());
|
||||
@ -2441,6 +2473,7 @@ jit::Invalidate(types::TypeCompartment &types, FreeOp *fop,
|
||||
if (!co.isValid())
|
||||
continue;
|
||||
|
||||
if (cancelOffThread)
|
||||
CancelOffThreadIonCompile(co.script()->compartment(), co.script());
|
||||
|
||||
if (!co.ion())
|
||||
@ -2505,13 +2538,16 @@ jit::Invalidate(types::TypeCompartment &types, FreeOp *fop,
|
||||
}
|
||||
|
||||
void
|
||||
jit::Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses)
|
||||
jit::Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses,
|
||||
bool cancelOffThread)
|
||||
{
|
||||
jit::Invalidate(cx->compartment()->types, cx->runtime()->defaultFreeOp(), invalid, resetUses);
|
||||
jit::Invalidate(cx->compartment()->types, cx->runtime()->defaultFreeOp(), invalid, resetUses,
|
||||
cancelOffThread);
|
||||
}
|
||||
|
||||
bool
|
||||
jit::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses)
|
||||
jit::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses,
|
||||
bool cancelOffThread)
|
||||
{
|
||||
JS_ASSERT(script->hasIonScript());
|
||||
|
||||
@ -2532,14 +2568,14 @@ jit::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetU
|
||||
MOZ_ASSUME_UNREACHABLE("No such execution mode");
|
||||
}
|
||||
|
||||
Invalidate(cx, scripts, resetUses);
|
||||
Invalidate(cx, scripts, resetUses, cancelOffThread);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses)
|
||||
jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses, bool cancelOffThread)
|
||||
{
|
||||
return Invalidate(cx, script, SequentialExecution, resetUses);
|
||||
return Invalidate(cx, script, SequentialExecution, resetUses, cancelOffThread);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -94,7 +94,7 @@ struct IonOptions
|
||||
// asm.js programs.
|
||||
//
|
||||
// Default: true
|
||||
bool assertGraphConsistency;
|
||||
bool checkGraphConsistency;
|
||||
|
||||
// Toggles whether Unreachable Code Elimination is performed.
|
||||
//
|
||||
@ -228,7 +228,7 @@ struct IonOptions
|
||||
rangeAnalysis(true),
|
||||
checkRangeAnalysis(false),
|
||||
checkThreadSafety(false),
|
||||
assertGraphConsistency(true),
|
||||
checkGraphConsistency(true),
|
||||
uce(true),
|
||||
eaa(true),
|
||||
#ifdef CHECK_OSIPOINT_REGISTERS
|
||||
@ -330,6 +330,10 @@ MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_
|
||||
|
||||
MethodStatus CanEnterInParallel(JSContext *cx, HandleScript script);
|
||||
|
||||
MethodStatus
|
||||
Recompile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc,
|
||||
bool constructing);
|
||||
|
||||
enum IonExecStatus
|
||||
{
|
||||
// The method call had to be aborted due to a stack limit check. This
|
||||
@ -361,10 +365,14 @@ IonExecStatus FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args);
|
||||
|
||||
// Walk the stack and invalidate active Ion frames for the invalid scripts.
|
||||
void Invalidate(types::TypeCompartment &types, FreeOp *fop,
|
||||
const Vector<types::RecompileInfo> &invalid, bool resetUses = true);
|
||||
void Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses = true);
|
||||
bool Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses = true);
|
||||
bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true);
|
||||
const Vector<types::RecompileInfo> &invalid, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
void Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
bool Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
|
||||
void MarkValueFromIon(JSRuntime *rt, Value *vp);
|
||||
void MarkShapeFromIon(JSRuntime *rt, Shape **shapep);
|
||||
|
@ -1288,7 +1288,7 @@ void
|
||||
jit::AssertGraphCoherency(MIRGraph &graph)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!js_IonOptions.assertGraphConsistency)
|
||||
if (!js_IonOptions.checkGraphConsistency)
|
||||
return;
|
||||
AssertBasicGraphCoherency(graph);
|
||||
AssertReversePostOrder(graph);
|
||||
@ -1303,7 +1303,7 @@ jit::AssertExtendedGraphCoherency(MIRGraph &graph)
|
||||
// are split)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!js_IonOptions.assertGraphConsistency)
|
||||
if (!js_IonOptions.checkGraphConsistency)
|
||||
return;
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
|
@ -3435,8 +3435,7 @@ IonBuilder::jsop_try()
|
||||
return abort("Has try-finally");
|
||||
|
||||
// Try-catch within inline frames is not yet supported.
|
||||
if (isInlineBuilder())
|
||||
return abort("try-catch within inline frame");
|
||||
JS_ASSERT(script()->uninlineable && !isInlineBuilder());
|
||||
|
||||
graph().setHasTryBlock();
|
||||
|
||||
@ -9150,9 +9149,8 @@ IonBuilder::jsop_setarg(uint32_t arg)
|
||||
// required, then it means that any aliased argument set can never be observed, and
|
||||
// the frame does not actually need to be updated with the new arg value.
|
||||
if (info().argumentsAliasesFormals()) {
|
||||
// Try-catch within inline frames is not yet supported.
|
||||
if (isInlineBuilder())
|
||||
return abort("JSOP_SETARG with magic arguments in inlined function.");
|
||||
// JSOP_SETARG with magic arguments within inline frames is not yet supported.
|
||||
JS_ASSERT(script()->uninlineable && !isInlineBuilder());
|
||||
|
||||
MSetFrameArgument *store = MSetFrameArgument::New(alloc(), arg, val);
|
||||
current->add(store);
|
||||
|
@ -199,6 +199,9 @@ struct IonScript
|
||||
// Flag set if IonScript was compiled with SPS profiling enabled.
|
||||
bool hasSPSInstrumentation_;
|
||||
|
||||
// Flag for if this script is getting recompiled.
|
||||
bool recompiling_;
|
||||
|
||||
// Any kind of data needed by the runtime, these can be either cache
|
||||
// information or profiling info.
|
||||
uint32_t runtimeData_;
|
||||
@ -530,6 +533,18 @@ struct IonScript
|
||||
osrPcMismatchCounter_ = 0;
|
||||
}
|
||||
|
||||
void setRecompiling() {
|
||||
recompiling_ = true;
|
||||
}
|
||||
|
||||
bool isRecompiling() const {
|
||||
return recompiling_;
|
||||
}
|
||||
|
||||
void clearRecompiling() {
|
||||
recompiling_ = false;
|
||||
}
|
||||
|
||||
static void writeBarrierPre(Zone *zone, IonScript *ionScript);
|
||||
};
|
||||
|
||||
|
@ -1205,6 +1205,43 @@ MacroAssembler::handleFailure(ExecutionMode executionMode)
|
||||
sps_->reenter(*this, InvalidReg);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline bool
|
||||
IsCompilingAsmJS()
|
||||
{
|
||||
// asm.js compilation pushes an IonContext with a null JSCompartment.
|
||||
IonContext *ictx = MaybeGetIonContext();
|
||||
return ictx && ictx->compartment == nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void assume_unreachable_(const char *output) {
|
||||
MOZ_ReportAssertionFailure(output, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::assume_unreachable(const char *output)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// AsmJS forbids use of ImmPtr.
|
||||
if (!IsCompilingAsmJS()) {
|
||||
RegisterSet regs = RegisterSet::Volatile();
|
||||
PushRegsInMask(regs);
|
||||
|
||||
Register temp = regs.takeGeneral();
|
||||
|
||||
setupUnalignedABICall(1, temp);
|
||||
movePtr(ImmPtr(output), temp);
|
||||
passABIArg(temp);
|
||||
callWithABI(JS_FUNC_TO_DATA_PTR(void *, assume_unreachable_));
|
||||
|
||||
PopRegsInMask(RegisterSet::Volatile());
|
||||
}
|
||||
#endif
|
||||
|
||||
breakpoint();
|
||||
}
|
||||
|
||||
static void printf0_(const char *output) {
|
||||
printf("%s", output);
|
||||
}
|
||||
|
@ -1094,6 +1094,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
|
||||
void finish();
|
||||
|
||||
void assume_unreachable(const char *output);
|
||||
void printf(const char *output);
|
||||
void printf(const char *output, Register value);
|
||||
|
||||
|
@ -1128,7 +1128,7 @@ LinearScanAllocator::canCoexist(LiveInterval *a, LiveInterval *b)
|
||||
void
|
||||
LinearScanAllocator::validateIntervals()
|
||||
{
|
||||
if (!js_IonOptions.assertGraphConsistency)
|
||||
if (!js_IonOptions.checkGraphConsistency)
|
||||
return;
|
||||
|
||||
for (IntervalIterator i(active.begin()); i != active.end(); i++) {
|
||||
@ -1174,7 +1174,7 @@ LinearScanAllocator::validateIntervals()
|
||||
void
|
||||
LinearScanAllocator::validateAllocations()
|
||||
{
|
||||
if (!js_IonOptions.assertGraphConsistency)
|
||||
if (!js_IonOptions.checkGraphConsistency)
|
||||
return;
|
||||
|
||||
for (IntervalIterator i(handled.begin()); i != handled.end(); i++) {
|
||||
|
@ -600,7 +600,7 @@ class LiveRangeAllocator : protected RegisterAllocator
|
||||
void validateVirtualRegisters()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!js_IonOptions.assertGraphConsistency)
|
||||
if (!js_IonOptions.checkGraphConsistency)
|
||||
return;
|
||||
|
||||
for (size_t i = 1; i < graph.numVirtualRegisters(); i++) {
|
||||
|
@ -595,11 +595,11 @@ LIRGenerator::visitCallDirectEval(MCallDirectEval *ins)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!useBoxAtStart(lir, (string->type() == MIRType_String
|
||||
? LCallDirectEvalS::ThisValue
|
||||
: LCallDirectEvalV::ThisValue),
|
||||
thisValue))
|
||||
{
|
||||
if (string->type() == MIRType_String) {
|
||||
if (!useBoxAtStart(lir, LCallDirectEvalS::ThisValue, thisValue))
|
||||
return false;
|
||||
} else {
|
||||
if (!useBoxAtStart(lir, LCallDirectEvalV::ThisValue, thisValue))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -922,6 +922,28 @@ JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject type,
|
||||
return TypedObject::createDerived(cx, type, owner, offset);
|
||||
}
|
||||
|
||||
bool
|
||||
Recompile(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(cx->currentlyRunningInJit());
|
||||
JitActivationIterator activations(cx->runtime());
|
||||
IonFrameIterator iter(activations);
|
||||
|
||||
JS_ASSERT(iter.type() == IonFrame_Exit);
|
||||
++iter;
|
||||
|
||||
bool isConstructing = iter.isConstructing();
|
||||
RootedScript script(cx, iter.script());
|
||||
JS_ASSERT(script->hasIonScript());
|
||||
|
||||
MethodStatus status = Recompile(cx, script, nullptr, nullptr, isConstructing);
|
||||
if (status == Method_Error)
|
||||
return false;
|
||||
|
||||
JS_ASSERT(script->hasIonScript());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
@ -661,6 +661,7 @@ bool InitBaselineFrameForOsr(BaselineFrame *frame, StackFrame *interpFrame,
|
||||
JSObject *CreateDerivedTypedObj(JSContext *cx, HandleObject type,
|
||||
HandleObject owner, int32_t offset);
|
||||
|
||||
bool Recompile(JSContext *cx);
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
@ -1908,7 +1908,7 @@ CodeGeneratorARM::generateInvalidateEpilogue()
|
||||
|
||||
// We should never reach this point in JIT code -- the invalidation thunk should
|
||||
// pop the invalidated JS frame and return directly to its caller.
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Should have returned directly to its caller instead of here.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -801,7 +801,7 @@ JitRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f)
|
||||
if (cx->runtime()->jitSupportsFloatingPoint)
|
||||
masm.loadDouble(Address(sp, 0), ReturnFloatReg);
|
||||
else
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Unable to load into float reg, with no FP support.");
|
||||
masm.freeStack(sizeof(double));
|
||||
break;
|
||||
|
||||
|
@ -1771,7 +1771,7 @@ CodeGeneratorX86Shared::generateInvalidateEpilogue()
|
||||
|
||||
// We should never reach this point in JIT code -- the invalidation thunk should
|
||||
// pop the invalidated JS frame and return directly to its caller.
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Should have returned directly to its caller instead of here.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -687,7 +687,7 @@ JitRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f)
|
||||
if (cx->runtime()->jitSupportsFloatingPoint)
|
||||
masm.Pop(ReturnFloatReg);
|
||||
else
|
||||
masm.breakpoint();
|
||||
masm.assume_unreachable("Unable to pop to float reg, with no FP support.");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1432,25 +1432,52 @@ js_QuoteString(ExclusiveContext *cx, JSString *str, jschar quote)
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
static JSObject *
|
||||
GetBlockChainAtPC(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
StaticBlockObject *
|
||||
js::GetBlockChainAtPC(JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(script->containsPC(pc));
|
||||
JS_ASSERT(pc >= script->main());
|
||||
|
||||
ptrdiff_t offset = pc - script->main();
|
||||
|
||||
if (!script->hasBlockScopes())
|
||||
return nullptr;
|
||||
|
||||
if (pc < script->main())
|
||||
return nullptr;
|
||||
ptrdiff_t offset = pc - script->main();
|
||||
|
||||
BlockScopeArray *blockScopes = script->blockScopes();
|
||||
JSObject *blockChain = nullptr;
|
||||
for (uint32_t n = 0; n < blockScopes->length; n++) {
|
||||
const BlockScopeNote *note = &blockScopes->vector[n];
|
||||
if (note->start > offset)
|
||||
StaticBlockObject *blockChain = nullptr;
|
||||
|
||||
// Find the innermost block chain using a binary search.
|
||||
size_t bottom = 0;
|
||||
size_t top = blockScopes->length;
|
||||
|
||||
while (bottom < top) {
|
||||
size_t mid = bottom + (top - bottom) / 2;
|
||||
const BlockScopeNote *note = &blockScopes->vector[mid];
|
||||
if (note->start <= offset) {
|
||||
// Block scopes are ordered in the list by their starting offset, and since
|
||||
// blocks form a tree ones earlier in the list may cover the pc even if
|
||||
// later blocks end before the pc. This only happens when the earlier block
|
||||
// is a parent of the later block, so we need to check parents of |mid| in
|
||||
// the searched range for coverage.
|
||||
size_t check = mid;
|
||||
while (check >= bottom) {
|
||||
const BlockScopeNote *checkNote = &blockScopes->vector[check];
|
||||
JS_ASSERT(checkNote->start <= offset);
|
||||
if (offset <= checkNote->start + checkNote->length) {
|
||||
// We found a matching block chain but there may be inner ones
|
||||
// at a higher block chain index than mid. Continue the binary search.
|
||||
blockChain = &script->getObject(checkNote->index)->as<StaticBlockObject>();
|
||||
break;
|
||||
if (offset <= note->start + note->length)
|
||||
blockChain = script->getObject(note->index);
|
||||
}
|
||||
if (checkNote->parent == UINT32_MAX)
|
||||
break;
|
||||
check = checkNote->parent;
|
||||
}
|
||||
bottom = mid + 1;
|
||||
} else {
|
||||
top = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return blockChain;
|
||||
@ -1716,7 +1743,7 @@ JSAtom *
|
||||
ExpressionDecompiler::findLetVar(jsbytecode *pc, unsigned depth)
|
||||
{
|
||||
if (script->hasObjects()) {
|
||||
JSObject *chain = GetBlockChainAtPC(cx, script, pc);
|
||||
JSObject *chain = GetBlockChainAtPC(script, pc);
|
||||
if (!chain)
|
||||
return nullptr;
|
||||
JS_ASSERT(chain->is<BlockObject>());
|
||||
|
@ -777,6 +777,11 @@ GetNextPc(jsbytecode *pc)
|
||||
return pc + GetBytecodeLength(pc);
|
||||
}
|
||||
|
||||
class StaticBlockObject;
|
||||
|
||||
StaticBlockObject *
|
||||
GetBlockChainAtPC(JSScript *script, jsbytecode *pc);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
@ -318,12 +318,10 @@ OPDEF(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, JOF_BYTE)
|
||||
* containing the variable being accessed
|
||||
* uint16 slot: the slot containing the variable in the ScopeObject (this
|
||||
* 'slot' does not include RESERVED_SLOTS).
|
||||
* uint32 block: the index (into the script object table) of the block chain
|
||||
* at the point of the variable access.
|
||||
*/
|
||||
OPDEF(JSOP_GETALIASEDVAR, 136,"getaliasedvar",NULL, 9, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_CALLALIASEDVAR,137,"callaliasedvar",NULL, 9, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_SETALIASEDVAR, 138,"setaliasedvar",NULL, 9, 1, 1, JOF_SCOPECOORD|JOF_NAME|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_GETALIASEDVAR, 136,"getaliasedvar",NULL, 5, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_CALLALIASEDVAR,137,"callaliasedvar",NULL, 5, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_SETALIASEDVAR, 138,"setaliasedvar",NULL, 5, 1, 1, JOF_SCOPECOORD|JOF_NAME|JOF_SET|JOF_DETECTING)
|
||||
|
||||
OPDEF(JSOP_UNUSED139, 139, "unused139", NULL, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED140, 140, "unused140", NULL, 1, 0, 0, JOF_BYTE)
|
||||
|
@ -807,7 +807,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
BlockScopeNote *note = &script->blockScopes()->vector[i];
|
||||
if (!xdr->codeUint32(¬e->index) ||
|
||||
!xdr->codeUint32(¬e->start) ||
|
||||
!xdr->codeUint32(¬e->length))
|
||||
!xdr->codeUint32(¬e->length) ||
|
||||
!xdr->codeUint32(¬e->parent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ struct BlockScopeNote {
|
||||
uint32_t index; // Index of StaticScopeObject in the object array.
|
||||
uint32_t start; // Bytecode offset at which this scope starts.
|
||||
uint32_t length; // Bytecode length of scope.
|
||||
uint32_t padding; // Pad to 64-bit boundary.
|
||||
uint32_t parent; // Index of parent block scope in notes, or UINT32_MAX.
|
||||
};
|
||||
|
||||
struct ConstArray {
|
||||
|
@ -38,11 +38,10 @@ InnermostStaticScope(JSScript *script, jsbytecode *pc)
|
||||
JS_ASSERT(script->containsPC(pc));
|
||||
JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD);
|
||||
|
||||
uint32_t blockIndex = GET_UINT32_INDEX(pc + 2 * sizeof(uint16_t));
|
||||
|
||||
if (blockIndex == UINT32_MAX)
|
||||
StaticBlockObject *block = GetBlockChainAtPC(script, pc);
|
||||
if (block)
|
||||
return block;
|
||||
return script->function();
|
||||
return &script->getObject(blockIndex)->as<StaticBlockObject>();
|
||||
}
|
||||
|
||||
Shape *
|
||||
|
@ -22,7 +22,7 @@ namespace js {
|
||||
* and saved versions. If deserialization fails, the data should be
|
||||
* invalidated if possible.
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 155);
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 156);
|
||||
|
||||
class XDRBuffer {
|
||||
public:
|
||||
|
@ -4206,10 +4206,11 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t flags = ShouldPrerenderTransformedContent(aBuilder, mFrame, false) ?
|
||||
FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS : 0;
|
||||
nsRefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
|
||||
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetChildren(),
|
||||
aContainerParameters, &newTransformMatrix,
|
||||
FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS);
|
||||
aContainerParameters, &newTransformMatrix, flags);
|
||||
|
||||
if (!container) {
|
||||
return nullptr;
|
||||
|
@ -92,8 +92,7 @@ nsVideoFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||
// And now have it update its internal state
|
||||
element->UpdateState(false);
|
||||
|
||||
nsresult res = UpdatePosterSource(false);
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
UpdatePosterSource(false);
|
||||
|
||||
if (!aElements.AppendElement(mPosterImage))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -592,20 +591,22 @@ nsVideoFrame::GetVideoIntrinsicSize(nsRenderingContext *aRenderingContext)
|
||||
nsPresContext::CSSPixelsToAppUnits(size.height));
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsVideoFrame::UpdatePosterSource(bool aNotify)
|
||||
{
|
||||
NS_ASSERTION(HasVideoElement(), "Only call this on <video> elements.");
|
||||
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::poster)) {
|
||||
nsAutoString posterStr;
|
||||
element->GetPoster(posterStr);
|
||||
nsresult res = mPosterImage->SetAttr(kNameSpaceID_None,
|
||||
mPosterImage->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::src,
|
||||
posterStr,
|
||||
aNotify);
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
return NS_OK;
|
||||
} else {
|
||||
mPosterImage->UnsetAttr(kNameSpaceID_None, nsGkAtoms::poster, aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -614,8 +615,7 @@ nsVideoFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
int32_t aModType)
|
||||
{
|
||||
if (aAttribute == nsGkAtoms::poster && HasVideoElement()) {
|
||||
nsresult res = UpdatePosterSource(true);
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
UpdatePosterSource(true);
|
||||
}
|
||||
return nsContainerFrame::AttributeChanged(aNameSpaceID,
|
||||
aAttribute,
|
||||
|
@ -112,7 +112,7 @@ protected:
|
||||
// Sets the mPosterImage's src attribute to be the video's poster attribute,
|
||||
// if we're the frame for a video element. Only call on frames for video
|
||||
// elements, not for frames for audio elements.
|
||||
nsresult UpdatePosterSource(bool aNotify);
|
||||
void UpdatePosterSource(bool aNotify);
|
||||
|
||||
virtual ~nsVideoFrame();
|
||||
|
||||
|
@ -79,6 +79,7 @@ support-files = bug633762_iframe.html
|
||||
[test_bug831780.html]
|
||||
[test_bug841361.html]
|
||||
[test_bug904810.html]
|
||||
[test_bug938772.html]
|
||||
[test_contained_plugin_transplant.html]
|
||||
[test_image_selection.html]
|
||||
[test_image_selection_2.html]
|
||||
|
23
layout/generic/test/test_bug938772.html
Normal file
23
layout/generic/test/test_bug938772.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=938772
|
||||
-->
|
||||
<title>Test for Bug 938772</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=938772">Mozilla Bug 938772</a>
|
||||
<p id="display"></p>
|
||||
<iframe id="i"></iframe>
|
||||
<pre id="test">
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
i.onload = function() {
|
||||
ok(!i.contentDocument.getElementById("v").failed,
|
||||
"Check whether an error was reported");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
i.src = "data:text/html,<base href='http://basetag/basetag'><video id='v' onerror='v.failed=true'></video>";
|
||||
</script>
|
||||
|
@ -7,6 +7,7 @@ LIBS = \
|
||||
$(NSPR_LIBS) \
|
||||
$(NSS_LIBS) \
|
||||
$(REALTIME_LIBS) \
|
||||
$(MOZ_JS_LIBS) \
|
||||
$(DEPTH)/xpcom/glue/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/media/mtransport/standalone/$(LIB_PREFIX)mtransport_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/media/webrtc/signalingtest/signaling_ecc/$(LIB_PREFIX)ecc.$(LIB_SUFFIX) \
|
||||
|
@ -106,11 +106,10 @@ pref("dom.workers.sharedWorkers.enabled", false);
|
||||
pref("dom.enable_performance", true);
|
||||
|
||||
// Whether the Gamepad API is enabled
|
||||
pref("dom.gamepad.enabled", true);
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("dom.gamepad.enabled", false);
|
||||
pref("dom.gamepad.non_standard_events.enabled", false);
|
||||
#else
|
||||
pref("dom.gamepad.enabled", true);
|
||||
pref("dom.gamepad.non_standard_events.enabled", true);
|
||||
#endif
|
||||
|
||||
|
@ -665,7 +665,7 @@ struct nsTArray_CopyChooser {
|
||||
//
|
||||
template <class E>
|
||||
struct nsTArray_CopyChooser<JS::Heap<E> > {
|
||||
typedef nsTArray_CopyWithConstructors<E> Type;
|
||||
typedef nsTArray_CopyWithConstructors<JS::Heap<E> > Type;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
127
xpcom/glue/tests/gtest/TestGCPostBarriers.cpp
Normal file
127
xpcom/glue/tests/gtest/TestGCPostBarriers.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* Tests that generational garbage collection post-barriers are correctly
|
||||
* implemented for nsTArrays that contain JavaScript Values.
|
||||
*/
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "js/Tracer.h"
|
||||
#include "js/HeapAPI.h"
|
||||
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
|
||||
using namespace JS;
|
||||
using namespace mozilla;
|
||||
|
||||
typedef nsTArray<Heap<JSObject*> > ArrayT;
|
||||
|
||||
static void
|
||||
TraceArray(JSTracer* trc, void* data)
|
||||
{
|
||||
ArrayT* array = static_cast<ArrayT *>(data);
|
||||
for (unsigned i = 0; i < array->Length(); ++i)
|
||||
JS_CallHeapObjectTracer(trc, &array->ElementAt(i), "array-element");
|
||||
}
|
||||
|
||||
static void
|
||||
RunTest(JSRuntime* rt, JSContext* cx)
|
||||
{
|
||||
JS_GC(rt);
|
||||
|
||||
/*
|
||||
* Create an array with space for half the final number of elements to test
|
||||
* that moving Heap<T> elements works correctly.
|
||||
*/
|
||||
const int elements = 100;
|
||||
ArrayT* array = new ArrayT(elements / 2);
|
||||
ASSERT_TRUE(array != nullptr);
|
||||
JS_AddExtraGCRootsTracer(rt, TraceArray, array);
|
||||
|
||||
/*
|
||||
* Create the array and fill it with new JS objects. With GGC these will be
|
||||
* allocated in the nursery.
|
||||
*/
|
||||
RootedValue value(cx);
|
||||
const char* property = "foo";
|
||||
JS::shadow::Runtime* srt = reinterpret_cast<JS::shadow::Runtime*>(rt);
|
||||
for (int i = 0; i < elements; ++i) {
|
||||
RootedObject obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
ASSERT_TRUE(js::gc::IsInsideNursery(srt, obj));
|
||||
#else
|
||||
ASSERT_FALSE(js::gc::IsInsideNursery(srt, obj));
|
||||
#endif
|
||||
value = Int32Value(i);
|
||||
ASSERT_TRUE(JS_SetProperty(cx, obj, property, value));
|
||||
array->AppendElement(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* If postbarriers are not working, we will crash here when we try to mark
|
||||
* objects that have been moved to the tenured heap.
|
||||
*/
|
||||
JS_GC(rt);
|
||||
|
||||
/*
|
||||
* Sanity check that our array contains what we expect.
|
||||
*/
|
||||
for (int i = 0; i < elements; ++i) {
|
||||
RootedObject obj(cx, array->ElementAt(i));
|
||||
ASSERT_FALSE(js::gc::IsInsideNursery(srt, obj));
|
||||
ASSERT_TRUE(JS_GetProperty(cx, obj, property, &value));
|
||||
ASSERT_TRUE(value.isInt32());
|
||||
ASSERT_EQ(i, value.toInt32());
|
||||
}
|
||||
|
||||
JS_RemoveExtraGCRootsTracer(rt, TraceArray, array);
|
||||
}
|
||||
|
||||
static void
|
||||
CreateGlobalAndRunTest(JSRuntime* rt, JSContext* cx)
|
||||
{
|
||||
static const JSClass GlobalClass = {
|
||||
"global", JSCLASS_GLOBAL_FLAGS,
|
||||
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
|
||||
};
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.setVersion(JSVERSION_LATEST);
|
||||
JS::RootedObject global(cx);
|
||||
global = JS_NewGlobalObject(cx, &GlobalClass, nullptr, JS::FireOnNewGlobalHook, options);
|
||||
ASSERT_TRUE(global != nullptr);
|
||||
|
||||
JS_AddNamedObjectRoot(cx, global.address(), "test-global");
|
||||
JSCompartment *oldCompartment = JS_EnterCompartment(cx, global);
|
||||
|
||||
RunTest(rt, cx);
|
||||
|
||||
JS_LeaveCompartment(cx, oldCompartment);
|
||||
JS_RemoveObjectRoot(cx, global.address());
|
||||
}
|
||||
|
||||
TEST(GCPostBarriers, nsTArray) {
|
||||
CycleCollectedJSRuntime* ccrt = CycleCollectedJSRuntime::Get();
|
||||
ASSERT_TRUE(ccrt != nullptr);
|
||||
JSRuntime* rt = ccrt->Runtime();
|
||||
ASSERT_TRUE(rt != nullptr);
|
||||
|
||||
JSContext *cx = JS_NewContext(rt, 8192);
|
||||
ASSERT_TRUE(cx != nullptr);
|
||||
JS_BeginRequest(cx);
|
||||
|
||||
CreateGlobalAndRunTest(rt, cx);
|
||||
|
||||
JS_EndRequest(cx);
|
||||
JS_DestroyContext(cx);
|
||||
}
|
@ -4,8 +4,9 @@
|
||||
# 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/.
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'TestFileUtils.cpp',
|
||||
'TestGCPostBarriers.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES = [
|
||||
|
Loading…
Reference in New Issue
Block a user