Merge m-c to b-i

This commit is contained in:
Phil Ringnalda 2013-12-07 15:15:53 -08:00
commit be814322b0
52 changed files with 511 additions and 144 deletions

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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,

View File

@ -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);

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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."),

View File

@ -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

View File

@ -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(&note);
note.index = scopeObject;
note.start = offset;
note.parent = parent;
return list.append(note);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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, &notnan);
masm.breakpoint();
masm.assume_unreachable("Input shouldn't be NaN.");
masm.bind(&notnan);
// 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, &notposinf);
masm.breakpoint();
masm.assume_unreachable("Input shouldn't be +Inf.");
masm.bind(&notposinf);
Label notneginf;
masm.loadConstantDouble(NegativeInfinity(), temp);
masm.branchDouble(Assembler::DoubleGreaterThan, input, temp, &notneginf);
masm.breakpoint();
masm.assume_unreachable("Input shouldn't be -Inf.");
masm.bind(&notneginf);
}
}
@ -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;
}

View File

@ -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)) {
SetIonScript(builder->script(), executionMode, ION_COMPILING_SCRIPT);
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,7 +2473,8 @@ jit::Invalidate(types::TypeCompartment &types, FreeOp *fop,
if (!co.isValid())
continue;
CancelOffThreadIonCompile(co.script()->compartment(), co.script());
if (cancelOffThread)
CancelOffThreadIonCompile(co.script()->compartment(), co.script());
if (!co.ion())
continue;
@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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++) {

View File

@ -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++) {

View File

@ -595,12 +595,12 @@ LIRGenerator::visitCallDirectEval(MCallDirectEval *ins)
return false;
}
if (!useBoxAtStart(lir, (string->type() == MIRType_String
? LCallDirectEvalS::ThisValue
: LCallDirectEvalV::ThisValue),
thisValue))
{
return false;
if (string->type() == MIRType_String) {
if (!useBoxAtStart(lir, LCallDirectEvalS::ThisValue, thisValue))
return false;
} else {
if (!useBoxAtStart(lir, LCallDirectEvalV::ThisValue, thisValue))
return false;
}
return defineReturn(lir, ins) && assignSafepoint(lir, ins);

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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:

View File

@ -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)
break;
if (offset <= note->start + note->length)
blockChain = script->getObject(note->index);
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 (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>());

View File

@ -777,6 +777,11 @@ GetNextPc(jsbytecode *pc)
return pc + GetBytecodeLength(pc);
}
class StaticBlockObject;
StaticBlockObject *
GetBlockChainAtPC(JSScript *script, jsbytecode *pc);
} /* namespace js */
#if defined(DEBUG)

View File

@ -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)

View File

@ -807,7 +807,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
BlockScopeNote *note = &script->blockScopes()->vector[i];
if (!xdr->codeUint32(&note->index) ||
!xdr->codeUint32(&note->start) ||
!xdr->codeUint32(&note->length))
!xdr->codeUint32(&note->length) ||
!xdr->codeUint32(&note->parent))
{
return false;
}

View File

@ -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 {

View File

@ -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)
return script->function();
return &script->getObject(blockIndex)->as<StaticBlockObject>();
StaticBlockObject *block = GetBlockChainAtPC(script, pc);
if (block)
return block;
return script->function();
}
Shape *

View File

@ -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:

View File

@ -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;

View File

@ -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());
nsAutoString posterStr;
element->GetPoster(posterStr);
nsresult res = mPosterImage->SetAttr(kNameSpaceID_None,
nsGkAtoms::src,
posterStr,
aNotify);
NS_ENSURE_SUCCESS(res,res);
return NS_OK;
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::poster)) {
nsAutoString posterStr;
element->GetPoster(posterStr);
mPosterImage->SetAttr(kNameSpaceID_None,
nsGkAtoms::src,
posterStr,
aNotify);
} 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,

View File

@ -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();

View File

@ -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]

View 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>

View File

@ -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) \

View File

@ -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

View File

@ -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<>

View 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);
}

View File

@ -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 = [