зеркало из https://github.com/mozilla/pjs.git
Bug 603077: OOM safety for JM assembler buffer, r=dvander
This commit is contained in:
Родитель
89f0cb9ad6
Коммит
be2b800be0
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче