Bug 816378 - Backout 5158d648702e (Bug 813773). a=bustage,Waldo

--HG--
rename : mobile/android/config/tooltool-manifests/android-x86/android/releng.manifest => mobile/android/config/tooltool-manifests/android/releng.manifest
extra : rebase_source : c2cb0190de4ad637dc3cd35a1876e9f06c16bcba
This commit is contained in:
Hubert Figuière 2012-11-28 23:00:56 -05:00
parent be476cbbc6
commit e03fccd6ba
8 changed files with 103 additions and 24 deletions

View File

@ -831,6 +831,8 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
// Known-target case is handled by LCallKnown.
JS_ASSERT(!call->hasSingleTarget());
// Unknown constructor case is handled by LCallConstructor.
JS_ASSERT(!call->mir()->isConstructing());
// Generate an ArgumentsRectifier.
IonCompartment *ion = gen->ionCompartment();
@ -901,16 +903,6 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
return false;
masm.bind(&end);
// If the return value of the constructing function is Primitive,
// replace the return value with the Object from CreateThis.
if (call->mir()->isConstructing()) {
Label notPrimitive;
masm.branchTestPrimitive(Assembler::NotEqual, JSReturnOperand, &notPrimitive);
masm.loadValue(Address(StackPointer, unusedStack), JSReturnOperand);
masm.bind(&notPrimitive);
}
dropArguments(call->numStackArgs() + 1);
return true;
}
@ -1001,6 +993,39 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
return true;
}
typedef bool (*InvokeConstructorFn)(JSContext *, JSObject *, uint32, Value *, Value *);
static const VMFunction InvokeConstructorInfo =
FunctionInfo<InvokeConstructorFn>(ion::InvokeConstructor);
bool
CodeGenerator::visitCallConstructor(LCallConstructor *call)
{
JS_ASSERT(call->mir()->isConstructing());
// Holds the function object.
const LAllocation *callee = call->getFunction();
Register calleereg = ToRegister(callee);
uint32 callargslot = call->argslot();
uint32 unusedStack = StackOffsetOfPassedArg(callargslot);
// Nestle %esp up to the argument vector.
masm.freeStack(unusedStack);
pushArg(StackPointer); // argv.
pushArg(Imm32(call->numActualArgs())); // argc.
pushArg(calleereg); // JSFunction *.
if (!callVM(InvokeConstructorInfo, call))
return false;
// Un-nestle %esp from the argument vector. No prefix was pushed.
masm.reserveStack(unusedStack);
dropArguments(call->numStackArgs() + 1);
return true;
}
bool
CodeGenerator::emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize)
{

View File

@ -79,6 +79,7 @@ class CodeGenerator : public CodeGeneratorSpecific
uint32 argc, uint32 unusedStack);
bool visitCallGeneric(LCallGeneric *call);
bool visitCallKnown(LCallKnown *call);
bool visitCallConstructor(LCallConstructor *call);
bool emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize);
void emitPushArguments(LApplyArgsGeneric *apply, Register extraStackSpace);
void emitPopArguments(LApplyArgsGeneric *apply, Register extraStackSize);

View File

@ -3579,27 +3579,24 @@ IonBuilder::createThisScriptedSingleton(HandleFunction target, HandleObject prot
MDefinition *
IonBuilder::createThis(HandleFunction target, MDefinition *callee)
{
// Create this for unknown target
if (!target)
return createThisScripted(callee);
// Create this for native function
if (target->isNative()) {
if (!target->isNativeConstructor())
return NULL;
return createThisNative();
}
// Create this with known prototype.
MDefinition *createThis = NULL;
RootedObject proto(cx, getSingletonPrototype(target));
if (proto) {
MDefinition *createThis = createThisScriptedSingleton(target, proto, callee);
if (createThis)
return createThis;
}
// Try baking in the prototype.
if (proto)
createThis = createThisScriptedSingleton(target, proto, callee);
// If the prototype could not be hardcoded, emit a GETPROP.
return createThisScripted(callee);
if (!createThis)
createThis = createThisScripted(callee);
return createThis;
}
bool
@ -3800,8 +3797,8 @@ IonBuilder::makeCallHelper(HandleFunction target, uint32 argc, bool constructing
MPassArg *thisArg = current->pop()->toPassArg();
// Inline the constructor on the caller-side.
if (constructing) {
// If the target is known, inline the constructor on the caller-side.
if (constructing && target) {
MDefinition *callee = current->peek(-1);
MDefinition *create = createThis(target, callee);
if (!create) {

View File

@ -665,6 +665,24 @@ class LCallDOMNative : public LJSCallInstructionHelper<BOX_PIECES, 0, 5>
}
};
// Generates a polymorphic callsite for |new|, where |this| has not been
// pre-allocated by the caller.
class LCallConstructor : public LJSCallInstructionHelper<BOX_PIECES, 1, 0>
{
public:
LIR_HEADER(CallConstructor);
LCallConstructor(const LAllocation &func, uint32 argslot)
: JSCallHelper(argslot)
{
setOperand(0, func);
}
const LAllocation *getFunction() {
return getOperand(0);
}
};
template <size_t defs, size_t ops>
class LDOMPropertyInstructionHelper : public LCallInstructionHelper<defs, 1 + ops, 3>
{

View File

@ -34,6 +34,7 @@
_(CallKnown) \
_(CallGeneric) \
_(CallNative) \
_(CallConstructor) \
_(ApplyArgsGeneric) \
_(StackArgT) \
_(StackArgV) \

View File

@ -290,6 +290,13 @@ LIRGenerator::visitCall(MCall *call)
return (defineReturn(lir, call) && assignSafepoint(lir, call));
}
// Call unknown constructors.
if (call->isConstructing()) {
LCallConstructor *lir = new LCallConstructor(useFixed(call->getFunction(),
CallTempReg0), argslot);
return (defineVMReturn(lir, call) && assignSafepoint(lir, call));
}
// Call anything, using the most generic code.
LCallGeneric *lir = new LCallGeneric(useFixed(call->getFunction(), CallTempReg0),
argslot, tempFixed(ArgumentsRectifierReg), tempFixed(CallTempReg2));

View File

@ -88,6 +88,35 @@ InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *
return ok;
}
bool
InvokeConstructor(JSContext *cx, JSObject *obj, uint32 argc, Value *argv, Value *rval)
{
Value fval = ObjectValue(*obj);
// See the comment in InvokeFunction.
bool needsMonitor;
if (obj->isFunction()) {
if (obj->toFunction()->isInterpretedLazy() &&
!obj->toFunction()->getOrCreateScript(cx).unsafeGet())
{
return false;
}
needsMonitor = ShouldMonitorReturnType(obj->toFunction());
} else {
needsMonitor = true;
}
// Data in the argument vector is arranged for a JIT -> JIT call.
Value *argvWithoutThis = argv + 1;
bool ok = js::InvokeConstructor(cx, fval, argc, argvWithoutThis, rval);
if (ok && needsMonitor)
types::TypeScript::Monitor(cx, *rval);
return ok;
}
JSObject *
NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize)
{

View File

@ -410,6 +410,7 @@ class AutoDetectInvalidation
};
bool InvokeFunction(JSContext *cx, JSFunction *fun, uint32 argc, Value *argv, Value *rval);
bool InvokeConstructor(JSContext *cx, JSObject *obj, uint32 argc, Value *argv, Value *rval);
JSObject *NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize);
bool CheckOverRecursed(JSContext *cx);