Bug 603077: OOM safety for JM assembler buffer, r=dvander

This commit is contained in:
David Mandelin 2010-10-14 16:33:49 -07:00
Родитель 89f0cb9ad6
Коммит be2b800be0
10 изменённых файлов: 208 добавлений и 82 удалений

Просмотреть файл

@ -416,7 +416,8 @@ void* ARMAssembler::executableCopy(ExecutablePool* allocator)
bkpt(0);
void * data = m_buffer.executableCopy(allocator);
fixUpOffsets(data);
if (data)
fixUpOffsets(data);
return data;
}
@ -426,6 +427,9 @@ void* ARMAssembler::executableCopy(ExecutablePool* allocator)
// have been flushed.
void* ARMAssembler::executableCopy(void * buffer)
{
if (m_buffer.oom())
return NULL;
ASSERT(m_buffer.sizeOfConstantPool() == 0);
memcpy(buffer, m_buffer.data(), m_buffer.size());

Просмотреть файл

@ -146,6 +146,7 @@ namespace JSC {
typedef SegmentedVector<int, 64> Jumps;
unsigned char *buffer() const { return m_buffer.buffer(); }
bool oom() const { return m_buffer.oom(); }
// ARM conditional constants
typedef enum {

Просмотреть файл

@ -1905,6 +1905,7 @@ private:
bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
void* data() const { return m_buffer.data(); }
void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
bool oom() const { return m_buffer.oom(); }
private:
AssemblerBuffer m_buffer;

Просмотреть файл

@ -446,6 +446,11 @@ public:
return m_assembler.buffer();
}
bool oom()
{
return m_assembler.oom();
}
void* executableCopy(void* buffer)
{
return m_assembler.executableCopy(buffer);

Просмотреть файл

@ -48,6 +48,7 @@ namespace JSC {
: m_buffer(m_inlineBuffer)
, m_capacity(inlineCapacity)
, m_size(0)
, m_oom(false)
{
}
@ -127,8 +128,20 @@ namespace JSC {
return m_size;
}
bool oom() const
{
return m_oom;
}
/*
* The user must check for a NULL return value, which means
* no code was generated, or there was an OOM.
*/
void* executableCopy(ExecutablePool* allocator)
{
if (m_oom)
return 0;
if (!m_size)
return 0;
@ -143,6 +156,7 @@ namespace JSC {
}
unsigned char *buffer() const {
ASSERT(!m_oom);
return reinterpret_cast<unsigned char *>(m_buffer);
}
@ -152,25 +166,59 @@ namespace JSC {
if (m_size > m_capacity - size)
grow(size);
// If we OOM and size > inlineCapacity, this would crash.
if (m_oom)
return;
memcpy(m_buffer + m_size, data, size);
m_size += size;
}
/*
* OOM handling: This class can OOM in the grow() method trying to
* allocate a new buffer. In response to an OOM, we need to avoid
* crashing and report the error. We also want to make it so that
* users of this class need to check for OOM only at certain points
* and not after every operation.
*
* Our strategy for handling an OOM is to set m_oom, and then set
* m_size to 0, preserving the current buffer. This way, the user
* can continue assembling into the buffer, deferring OOM checking
* until the user wants to read code out of the buffer.
*
* See also the |executableCopy| and |buffer| methods.
*/
void grow(int extraCapacity = 0)
{
m_capacity += m_capacity / 2 + extraCapacity;
int newCapacity = m_capacity + m_capacity / 2 + extraCapacity;
char* newBuffer;
if (m_buffer == m_inlineBuffer) {
char* newBuffer = static_cast<char*>(malloc(m_capacity));
m_buffer = static_cast<char*>(memcpy(newBuffer, m_buffer, m_size));
} else
m_buffer = static_cast<char*>(realloc(m_buffer, m_capacity));
newBuffer = static_cast<char*>(malloc(newCapacity));
if (!newBuffer) {
m_size = 0;
m_oom = true;
return;
}
memcpy(newBuffer, m_buffer, m_size);
} else {
newBuffer = static_cast<char*>(realloc(m_buffer, newCapacity));
if (!newBuffer) {
m_size = 0;
m_oom = true;
return;
}
}
m_buffer = newBuffer;
m_capacity = newCapacity;
}
char m_inlineBuffer[inlineCapacity];
char* m_buffer;
int m_capacity;
int m_size;
bool m_oom;
};
} // namespace JSC

Просмотреть файл

@ -363,6 +363,7 @@ public:
size_t size() const { return m_formatter.size(); }
unsigned char *buffer() const { return m_formatter.buffer(); }
bool oom() const { return m_formatter.oom(); }
// Stack operations:
@ -2222,12 +2223,13 @@ public:
void* executableCopy(ExecutablePool* allocator)
{
void* copy = m_formatter.executableCopy(allocator);
ASSERT(copy);
return copy;
}
void* executableCopy(void* buffer)
{
if (m_formatter.oom())
return NULL;
return memcpy(buffer, m_formatter.buffer(), size());
}
@ -2541,6 +2543,7 @@ private:
size_t size() const { return m_buffer.size(); }
unsigned char *buffer() const { return m_buffer.buffer(); }
bool oom() const { return m_buffer.oom(); }
bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
void* data() const { return m_buffer.data(); }
void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }

Просмотреть файл

@ -67,6 +67,14 @@ using namespace js::mjit::ic;
#define ADD_CALLSITE(stub) if (debugMode) addCallSite(__LINE__, (stub))
#define RETURN_IF_OOM(retval) \
JS_BEGIN_MACRO \
if (masm.oom() || stubcc.masm.oom()) { \
js_ReportOutOfMemory(cx); \
return retval; \
} \
JS_END_MACRO
#if defined(JS_METHODJIT_SPEW)
static const char *OpcodeNames[] = {
# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) #name,
@ -319,6 +327,8 @@ mjit::Compiler::generateEpilogue()
CompileStatus
mjit::Compiler::finishThisUp(JITScript **jitp)
{
RETURN_IF_OOM(Compile_Error);
for (size_t i = 0; i < branchPatches.length(); i++) {
Label label = labelOf(branchPatches[i].pc);
branchPatches[i].jump.linkTo(label, &masm);
@ -342,7 +352,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
JSC::ExecutableAllocator::makeWritable(result, totalSize);
masm.executableCopy(result);
stubcc.masm.executableCopy(result + masm.size());
JSC::LinkBuffer fullCode(result, totalSize);
JSC::LinkBuffer stubCode(result + masm.size(), stubcc.size());
@ -955,7 +965,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_VOID)
BEGIN_CASE(JSOP_INCNAME)
jsop_nameinc(op, STRICT_VARIANT(stubs::IncName), fullAtomIndex(PC));
if (!jsop_nameinc(op, STRICT_VARIANT(stubs::IncName), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_INCNAME)
@ -965,7 +976,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_INCGNAME)
BEGIN_CASE(JSOP_INCPROP)
jsop_propinc(op, STRICT_VARIANT(stubs::IncProp), fullAtomIndex(PC));
if (!jsop_propinc(op, STRICT_VARIANT(stubs::IncProp), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_INCPROP)
@ -974,7 +986,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_INCELEM)
BEGIN_CASE(JSOP_DECNAME)
jsop_nameinc(op, STRICT_VARIANT(stubs::DecName), fullAtomIndex(PC));
if (!jsop_nameinc(op, STRICT_VARIANT(stubs::DecName), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_DECNAME)
@ -984,7 +997,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_DECGNAME)
BEGIN_CASE(JSOP_DECPROP)
jsop_propinc(op, STRICT_VARIANT(stubs::DecProp), fullAtomIndex(PC));
if (!jsop_propinc(op, STRICT_VARIANT(stubs::DecProp), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_DECPROP)
@ -993,7 +1007,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_DECELEM)
BEGIN_CASE(JSOP_NAMEINC)
jsop_nameinc(op, STRICT_VARIANT(stubs::NameInc), fullAtomIndex(PC));
if (!jsop_nameinc(op, STRICT_VARIANT(stubs::NameInc), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_NAMEINC)
@ -1003,7 +1018,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_GNAMEINC)
BEGIN_CASE(JSOP_PROPINC)
jsop_propinc(op, STRICT_VARIANT(stubs::PropInc), fullAtomIndex(PC));
if (!jsop_propinc(op, STRICT_VARIANT(stubs::PropInc), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_PROPINC)
@ -1012,7 +1028,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_ELEMINC)
BEGIN_CASE(JSOP_NAMEDEC)
jsop_nameinc(op, STRICT_VARIANT(stubs::NameDec), fullAtomIndex(PC));
if (!jsop_nameinc(op, STRICT_VARIANT(stubs::NameDec), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_NAMEDEC)
@ -1022,7 +1039,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_GNAMEDEC)
BEGIN_CASE(JSOP_PROPDEC)
jsop_propinc(op, STRICT_VARIANT(stubs::PropDec), fullAtomIndex(PC));
if (!jsop_propinc(op, STRICT_VARIANT(stubs::PropDec), fullAtomIndex(PC)))
return Compile_Error;
break;
END_CASE(JSOP_PROPDEC)
@ -1033,30 +1051,36 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_GETTHISPROP)
/* Push thisv onto stack. */
jsop_this();
jsop_getprop(script->getAtom(fullAtomIndex(PC)));
if (!jsop_getprop(script->getAtom(fullAtomIndex(PC))))
return Compile_Error;
END_CASE(JSOP_GETTHISPROP);
BEGIN_CASE(JSOP_GETARGPROP)
/* Push arg onto stack. */
jsop_getarg(GET_SLOTNO(PC));
jsop_getprop(script->getAtom(fullAtomIndex(&PC[ARGNO_LEN])));
if (!jsop_getprop(script->getAtom(fullAtomIndex(&PC[ARGNO_LEN]))))
return Compile_Error;
END_CASE(JSOP_GETARGPROP)
BEGIN_CASE(JSOP_GETLOCALPROP)
frame.pushLocal(GET_SLOTNO(PC));
jsop_getprop(script->getAtom(fullAtomIndex(&PC[SLOTNO_LEN])));
if (!jsop_getprop(script->getAtom(fullAtomIndex(&PC[SLOTNO_LEN]))))
return Compile_Error;
END_CASE(JSOP_GETLOCALPROP)
BEGIN_CASE(JSOP_GETPROP)
jsop_getprop(script->getAtom(fullAtomIndex(PC)));
if (!jsop_getprop(script->getAtom(fullAtomIndex(PC))))
return Compile_Error;
END_CASE(JSOP_GETPROP)
BEGIN_CASE(JSOP_LENGTH)
jsop_length();
if (!jsop_length())
return Compile_Error;
END_CASE(JSOP_LENGTH)
BEGIN_CASE(JSOP_GETELEM)
jsop_getelem();
if (!jsop_getelem())
return Compile_Error;
END_CASE(JSOP_GETELEM)
BEGIN_CASE(JSOP_SETELEM)
@ -1347,12 +1371,14 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_BINDNAME)
BEGIN_CASE(JSOP_SETPROP)
jsop_setprop(script->getAtom(fullAtomIndex(PC)));
if (!jsop_setprop(script->getAtom(fullAtomIndex(PC))))
return Compile_Error;
END_CASE(JSOP_SETPROP)
BEGIN_CASE(JSOP_SETNAME)
BEGIN_CASE(JSOP_SETMETHOD)
jsop_setprop(script->getAtom(fullAtomIndex(PC)));
if (!jsop_setprop(script->getAtom(fullAtomIndex(PC))))
return Compile_Error;
END_CASE(JSOP_SETNAME)
BEGIN_CASE(JSOP_THROW)
@ -1370,7 +1396,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_IN)
BEGIN_CASE(JSOP_INSTANCEOF)
jsop_instanceof();
if (!jsop_instanceof())
return Compile_Error;
END_CASE(JSOP_INSTANCEOF)
BEGIN_CASE(JSOP_EXCEPTION)
@ -1598,7 +1625,8 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_STOP)
BEGIN_CASE(JSOP_GETXPROP)
jsop_xname(script->getAtom(fullAtomIndex(PC)));
if (!jsop_xname(script->getAtom(fullAtomIndex(PC))))
return Compile_Error;
END_CASE(JSOP_GETXPROP)
BEGIN_CASE(JSOP_ENTERBLOCK)
@ -1703,8 +1731,10 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_GLOBALINC)
BEGIN_CASE(JSOP_BEGIN)
if (isConstructing)
constructThis();
if (isConstructing) {
if (!constructThis())
return Compile_Error;
}
END_CASE(JSOP_BEGIN)
default:
@ -2392,7 +2422,7 @@ mjit::Compiler::jsop_callprop_slow(JSAtom *atom)
return true;
}
void
bool
mjit::Compiler::jsop_length()
{
FrameEntry *top = frame.peek(-1);
@ -2411,16 +2441,17 @@ mjit::Compiler::jsop_length()
frame.pop();
frame.pushTypedPayload(JSVAL_TYPE_INT32, str);
}
return;
return true;
}
#if defined JS_POLYIC
jsop_getprop(cx->runtime->atomState.lengthAtom);
return jsop_getprop(cx->runtime->atomState.lengthAtom);
#else
prepareStubCall(Uses(1));
stubCall(stubs::Length);
frame.pop();
frame.pushSynced();
return true;
#endif
}
@ -2439,7 +2470,7 @@ mjit::Compiler::passPICAddress(PICGenInfo &pic)
pic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
}
void
bool
mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
{
FrameEntry *top = frame.peek(-1);
@ -2449,7 +2480,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
JS_ASSERT_IF(atom == cx->runtime->atomState.lengthAtom,
top->getKnownType() != JSVAL_TYPE_STRING);
jsop_getprop_slow();
return;
return true;
}
/*
@ -2477,6 +2508,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
Jump j = masm.testObject(Assembler::NotEqual, reg);
/* GETPROP_INLINE_TYPE_GUARD is used to patch the jmp, not cmp. */
RETURN_IF_OOM(false);
JS_ASSERT(masm.differenceBetween(pic.fastPathStart, masm.label()) == GETPROP_INLINE_TYPE_GUARD);
pic.typeCheck = stubcc.linkExit(j, Uses(1));
@ -2536,8 +2568,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
#endif
pic.storeBack = masm.label();
/* Assert correctness of hardcoded offsets. */
RETURN_IF_OOM(false);
#if defined JS_NUNBOX32
JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD);
@ -2564,10 +2596,11 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
stubcc.rejoin(Changes(1));
pics.append(pic);
return true;
}
#ifdef JS_POLYIC
void
bool
mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg,
RegisterID idReg, RegisterID shapeReg)
{
@ -2637,6 +2670,7 @@ mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID obj
pic.objReg = objReg;
pic.idReg = idReg;
RETURN_IF_OOM(false);
#if defined JS_NUNBOX32
JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETELEM_DSLOTS_LOAD);
JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETELEM_TYPE_LOAD);
@ -2668,6 +2702,7 @@ mjit::Compiler::jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID obj
JS_ASSERT(pic.objReg != pic.shapeReg);
pics.append(pic);
return true;
}
#endif
@ -2768,6 +2803,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
pic.storeBack = masm.label();
/* Assert correctness of hardcoded offsets. */
RETURN_IF_OOM(false);
JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgInlineTypeGuard) == GETPROP_INLINE_TYPE_GUARD);
#if defined JS_NUNBOX32
JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
@ -2814,7 +2850,8 @@ mjit::Compiler::jsop_callprop_str(JSAtom *atom)
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
/* Get the property. */
jsop_getprop(atom);
if (!jsop_getprop(atom))
return false;
/* Perform a swap. */
frame.dup2();
@ -2926,6 +2963,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
* Assert correctness of hardcoded offsets.
* No type guard: type is asserted.
*/
RETURN_IF_OOM(false);
#if defined JS_NUNBOX32
JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
JS_ASSERT(masm.differenceBetween(pic.storeBack, dbgTypeLoad) == GETPROP_TYPE_LOAD);
@ -2968,7 +3006,7 @@ mjit::Compiler::jsop_callprop(JSAtom *atom)
return jsop_callprop_generic(atom);
}
void
bool
mjit::Compiler::jsop_setprop(JSAtom *atom)
{
FrameEntry *lhs = frame.peek(-2);
@ -2977,7 +3015,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
/* If the incoming type will never PIC, take slow path. */
if (lhs->isTypeKnown() && lhs->getKnownType() != JSVAL_TYPE_OBJECT) {
jsop_setprop_slow(atom);
return;
return true;
}
JSOp op = JSOp(*PC);
@ -3083,6 +3121,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
stubcc.rejoin(Changes(1));
}
RETURN_IF_OOM(false);
#if defined JS_PUNBOX64
pic.labels.setprop.dslotsLoadOffset = masm.differenceBetween(pic.storeBack, dslotsLoadLabel);
pic.labels.setprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel);
@ -3108,6 +3147,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
#endif
pics.append(pic);
return true;
}
void
@ -3142,15 +3182,14 @@ mjit::Compiler::jsop_name(JSAtom *atom)
pics.append(pic);
}
void
bool
mjit::Compiler::jsop_xname(JSAtom *atom)
{
PICGenInfo pic(ic::PICInfo::XNAME);
FrameEntry *fe = frame.peek(-1);
if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
jsop_getprop(atom);
return;
return jsop_getprop(atom);
}
if (!fe->isTypeKnown()) {
@ -3184,6 +3223,7 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
stubcc.rejoin(Changes(1));
pics.append(pic);
return true;
}
void
@ -3243,16 +3283,17 @@ mjit::Compiler::jsop_name(JSAtom *atom)
frame.pushSynced();
}
void
bool
mjit::Compiler::jsop_xname(JSAtom *atom)
{
jsop_getprop(atom);
return jsop_getprop(atom);
}
void
bool
mjit::Compiler::jsop_getprop(JSAtom *atom, bool typecheck)
{
jsop_getprop_slow();
return true;
}
bool
@ -3261,10 +3302,11 @@ mjit::Compiler::jsop_callprop(JSAtom *atom)
return jsop_callprop_slow(atom);
}
void
bool
mjit::Compiler::jsop_setprop(JSAtom *atom)
{
jsop_setprop_slow(atom);
return true;
}
void
@ -3401,7 +3443,7 @@ mjit::Compiler::jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index)
PC += JSOP_GNAMEINC_LENGTH;
}
void
bool
mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
{
JSAtom *atom = script->getAtom(index);
@ -3435,7 +3477,8 @@ mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
frame.shift(-1);
// OBJ V+1
jsop_setprop(atom);
if (!jsop_setprop(atom))
return false;
// V+1
if (pop)
@ -3470,7 +3513,8 @@ mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
frame.shift(-1);
// N OBJ N+1
jsop_setprop(atom);
if (!jsop_setprop(atom))
return false;
// N N+1
frame.pop();
@ -3487,9 +3531,10 @@ mjit::Compiler::jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index)
#endif
PC += JSOP_NAMEINC_LENGTH;
return true;
}
void
bool
mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
{
JSAtom *atom = script->getAtom(index);
@ -3506,7 +3551,8 @@ mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
frame.dup();
// OBJ OBJ
jsop_getprop(atom);
if (!jsop_getprop(atom))
return false;
// OBJ V
frame.push(Int32Value(amt));
@ -3516,7 +3562,8 @@ mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
jsop_binary(JSOP_SUB, stubs::Sub);
// OBJ V+1
jsop_setprop(atom);
if (!jsop_setprop(atom))
return false;
// V+1
if (pop)
@ -3527,7 +3574,8 @@ mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
frame.dup();
// OBJ OBJ
jsop_getprop(atom);
if (!jsop_getprop(atom))
return false;
// OBJ V
jsop_pos();
@ -3548,7 +3596,8 @@ mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
frame.dupAt(-2);
// OBJ N N+1 OBJ N+1
jsop_setprop(atom);
if (!jsop_setprop(atom))
return false;
// OBJ N N+1 N+1
frame.popn(2);
@ -3570,6 +3619,7 @@ mjit::Compiler::jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index)
}
PC += JSOP_PROPINC_LENGTH;
return true;
}
void
@ -4124,7 +4174,7 @@ mjit::Compiler::jsop_unbrand()
stubCall(stubs::Unbrand);
}
void
bool
mjit::Compiler::jsop_instanceof()
{
FrameEntry *lhs = frame.peek(-2);
@ -4137,7 +4187,7 @@ mjit::Compiler::jsop_instanceof()
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, Registers::ReturnReg);
return;
return true;
}
MaybeJump firstSlow;
@ -4164,7 +4214,8 @@ mjit::Compiler::jsop_instanceof()
/* This is sadly necessary because the error case needs the object. */
frame.dup();
jsop_getprop(cx->runtime->atomState.classPrototypeAtom, false);
if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, false))
return false;
/* Primitive prototypes are invalid. */
rhs = frame.peek(-1);
@ -4216,6 +4267,7 @@ mjit::Compiler::jsop_instanceof()
if (firstSlow.isSet())
firstSlow.getJump().linkTo(stubcc.masm.label(), &stubcc.masm);
stubcc.rejoin(Changes(1));
return true;
}
/*
@ -4341,7 +4393,7 @@ mjit::Compiler::leaveBlock()
// NULL
// call js_CreateThisFromFunctionWithProto(...)
//
void
bool
mjit::Compiler::constructThis()
{
JS_ASSERT(isConstructing);
@ -4353,7 +4405,8 @@ mjit::Compiler::constructThis()
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, calleeReg);
// Get callee.prototype.
jsop_getprop(cx->runtime->atomState.classPrototypeAtom);
if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom))
return false;
// Reach into the proto Value and grab a register for its data.
FrameEntry *protoFe = frame.peek(-1);
@ -4373,5 +4426,6 @@ mjit::Compiler::constructThis()
masm.move(protoReg, Registers::ArgReg1);
stubCall(stubs::CreateThis);
frame.freeReg(protoReg);
return true;
}

Просмотреть файл

@ -271,7 +271,7 @@ class Compiler : public BaseCompiler
#ifdef JS_MONOIC
void passMICAddress(MICGenInfo &mic);
#endif
void constructThis();
bool constructThis();
/* Opcode handlers. */
void jumpAndTrace(Jump j, jsbytecode *target, Jump *slowOne = NULL, Jump *slowTwo = NULL);
@ -291,8 +291,8 @@ class Compiler : public BaseCompiler
void inlineCallHelper(uint32 argc, bool callingNew);
void fixPrimitiveReturn(Assembler *masm, FrameEntry *fe);
void jsop_gnameinc(JSOp op, VoidStubAtom stub, uint32 index);
void jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
void jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
bool jsop_nameinc(JSOp op, VoidStubAtom stub, uint32 index);
bool jsop_propinc(JSOp op, VoidStubAtom stub, uint32 index);
void jsop_eleminc(JSOp op, VoidStub);
void jsop_getgname(uint32 index);
void jsop_getgname_slow(uint32 index);
@ -302,18 +302,18 @@ class Compiler : public BaseCompiler
void jsop_setelem_slow();
void jsop_getelem_slow();
void jsop_unbrand();
void jsop_getprop(JSAtom *atom, bool typeCheck = true);
void jsop_length();
void jsop_setprop(JSAtom *atom);
bool jsop_getprop(JSAtom *atom, bool typeCheck = true);
bool jsop_length();
bool jsop_setprop(JSAtom *atom);
void jsop_setprop_slow(JSAtom *atom);
bool jsop_callprop_slow(JSAtom *atom);
bool jsop_callprop(JSAtom *atom);
bool jsop_callprop_obj(JSAtom *atom);
bool jsop_callprop_str(JSAtom *atom);
bool jsop_callprop_generic(JSAtom *atom);
void jsop_instanceof();
bool jsop_instanceof();
void jsop_name(JSAtom *atom);
void jsop_xname(JSAtom *atom);
bool jsop_xname(JSAtom *atom);
void enterBlock(JSObject *obj);
void leaveBlock();
@ -365,11 +365,11 @@ class Compiler : public BaseCompiler
void jsop_arginc(JSOp op, uint32 slot, bool popped);
void jsop_localinc(JSOp op, uint32 slot, bool popped);
void jsop_setelem();
void jsop_getelem();
void jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
void jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
bool jsop_getelem();
bool jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
bool jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
void jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg);
void jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg,
bool jsop_getelem_pic(FrameEntry *obj, FrameEntry *id, RegisterID objReg, RegisterID idReg,
RegisterID shapeReg);
void jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID objReg,
MaybeRegisterID &idReg, RegisterID shapeReg);

Просмотреть файл

@ -1398,7 +1398,7 @@ mjit::Compiler::jsop_getelem_dense(FrameEntry *obj, FrameEntry *id, RegisterID o
/* Note: linkExits will be hooked up to a leave() after this method completes. */
}
void
bool
mjit::Compiler::jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg)
{
switch (id->getKnownType()) {
@ -1421,7 +1421,7 @@ mjit::Compiler::jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, Registe
frame.popn(2);
frame.pushRegs(tmpReg, objReg);
stubcc.rejoin(Changes(1));
return;
break;
}
#ifdef JS_POLYIC
case JSVAL_TYPE_STRING:
@ -1431,23 +1431,25 @@ mjit::Compiler::jsop_getelem_known_type(FrameEntry *obj, FrameEntry *id, Registe
RegisterID idReg = frame.copyDataIntoReg(id);
/* Meat. */
jsop_getelem_pic(obj, id, objReg, idReg, tmpReg);
if (!jsop_getelem_pic(obj, id, objReg, idReg, tmpReg))
return false;
/* Epilogue. */
frame.popn(2);
frame.pushRegs(tmpReg, objReg);
frame.freeReg(idReg);
stubcc.rejoin(Changes(1));
return;
break;
}
#endif
default:
JS_NOT_REACHED("Invalid known id type.");
}
return true;
}
#ifdef JS_POLYIC
void
bool
mjit::Compiler::jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterID tmpReg)
{
JS_ASSERT(!id->isTypeKnown());
@ -1472,13 +1474,15 @@ mjit::Compiler::jsop_getelem_with_pic(FrameEntry *obj, FrameEntry *id, RegisterI
stubcc.call(stubs::GetElem);
Jump toFinalMerge = stubcc.masm.jump();
jsop_getelem_pic(obj, id, objReg, idReg.reg(), tmpReg);
if (!jsop_getelem_pic(obj, id, objReg, idReg.reg(), tmpReg))
return false;
performedDense.linkTo(masm.label(), &masm);
frame.popn(2);
frame.pushRegs(tmpReg, objReg);
frame.freeReg(idReg.reg());
toFinalMerge.linkTo(stubcc.masm.label(), &stubcc.masm);
stubcc.rejoin(Changes(1));
return true;
}
#endif
@ -1504,7 +1508,7 @@ mjit::Compiler::jsop_getelem_nopic(FrameEntry *obj, FrameEntry *id, RegisterID t
stubcc.rejoin(Changes(1));
}
void
bool
mjit::Compiler::jsop_getelem()
{
FrameEntry *obj = frame.peek(-2);
@ -1512,7 +1516,7 @@ mjit::Compiler::jsop_getelem()
if (obj->isTypeKnown() && obj->getKnownType() != JSVAL_TYPE_OBJECT) {
jsop_getelem_slow();
return;
return true;
}
if (id->isTypeKnown() &&
@ -1522,19 +1526,19 @@ mjit::Compiler::jsop_getelem()
#endif
)) {
jsop_getelem_slow();
return;
return true;
}
if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_INT32 && id->isConstant() &&
id->getValue().toInt32() < 0) {
jsop_getelem_slow();
return;
return true;
}
if (id->isTypeKnown() && id->getKnownType() == JSVAL_TYPE_STRING && id->isConstant()) {
/* Never happens, or I'd optimize it. */
jsop_getelem_slow();
return;
return true;
}
RegisterID tmpReg;
@ -1552,7 +1556,8 @@ mjit::Compiler::jsop_getelem()
#ifdef JS_POLYIC
return jsop_getelem_with_pic(obj, id, tmpReg);
#else
return jsop_getelem_nopic(obj, id, tmpReg);
jsop_getelem_nopic(obj, id, tmpReg);
return true;
#endif
}

Просмотреть файл

@ -1523,6 +1523,11 @@ public:
{
generate();
if (oom()) {
m_shouldFallBack = true;
return;
}
ExecutablePool *executablePool = allocator.poolForSize(size());
if (!executablePool) {
m_shouldFallBack = true;