| Index: src/arm/lithium-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-arm.cc (revision 7180)
|
| +++ src/arm/lithium-arm.cc (working copy)
|
| @@ -346,7 +346,7 @@
|
| }
|
|
|
|
|
| -void LStoreNamed::PrintDataTo(StringStream* stream) {
|
| +void LStoreNamedField::PrintDataTo(StringStream* stream) {
|
| object()->PrintTo(stream);
|
| stream->Add(".");
|
| stream->Add(*String::cast(*name())->ToCString());
|
| @@ -355,8 +355,17 @@
|
| }
|
|
|
|
|
| -void LStoreKeyed::PrintDataTo(StringStream* stream) {
|
| +void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
|
| object()->PrintTo(stream);
|
| + stream->Add(".");
|
| + stream->Add(*String::cast(*name())->ToCString());
|
| + stream->Add(" <- ");
|
| + value()->PrintTo(stream);
|
| +}
|
| +
|
| +
|
| +void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
|
| + object()->PrintTo(stream);
|
| stream->Add("[");
|
| key()->PrintTo(stream);
|
| stream->Add("] <- ");
|
| @@ -364,8 +373,18 @@
|
| }
|
|
|
|
|
| -LChunk::LChunk(HGraph* graph)
|
| +void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
|
| + object()->PrintTo(stream);
|
| + stream->Add("[");
|
| + key()->PrintTo(stream);
|
| + stream->Add("] <- ");
|
| + value()->PrintTo(stream);
|
| +}
|
| +
|
| +
|
| +LChunk::LChunk(CompilationInfo* info, HGraph* graph)
|
| : spill_slot_count_(0),
|
| + info_(info),
|
| graph_(graph),
|
| instructions_(32),
|
| pointer_maps_(8),
|
| @@ -456,7 +475,7 @@
|
| // shift all parameter indexes down by the number of parameters, and
|
| // make sure they end up negative so they are distinguishable from
|
| // spill slots.
|
| - int result = index - graph()->info()->scope()->num_parameters() - 1;
|
| + int result = index - info()->scope()->num_parameters() - 1;
|
| ASSERT(result < 0);
|
| return result;
|
| }
|
| @@ -464,7 +483,7 @@
|
| // A parameter relative to ebp in the arguments stub.
|
| int LChunk::ParameterAt(int index) {
|
| ASSERT(-1 <= index); // -1 is the receiver.
|
| - return (1 + graph()->info()->scope()->num_parameters() - index) *
|
| + return (1 + info()->scope()->num_parameters() - index) *
|
| kPointerSize;
|
| }
|
|
|
| @@ -503,7 +522,7 @@
|
|
|
| LChunk* LChunkBuilder::Build() {
|
| ASSERT(is_unused());
|
| - chunk_ = new LChunk(graph());
|
| + chunk_ = new LChunk(info(), graph());
|
| HPhase phase("Building chunk", chunk_);
|
| status_ = BUILDING;
|
| const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
|
| @@ -520,8 +539,8 @@
|
|
|
| void LChunkBuilder::Abort(const char* format, ...) {
|
| if (FLAG_trace_bailout) {
|
| - SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
|
| - PrintF("Aborting LChunk building in @\"%s\": ", *debug_name);
|
| + SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
|
| + PrintF("Aborting LChunk building in @\"%s\": ", *name);
|
| va_list arguments;
|
| va_start(arguments, format);
|
| OS::VPrint(format, arguments);
|
| @@ -855,6 +874,7 @@
|
| ASSERT(instr->representation().IsDouble());
|
| ASSERT(instr->left()->representation().IsDouble());
|
| ASSERT(instr->right()->representation().IsDouble());
|
| + ASSERT(op != Token::MOD);
|
| LOperand* left = UseRegisterAtStart(instr->left());
|
| LOperand* right = UseRegisterAtStart(instr->right());
|
| LArithmeticD* result = new LArithmeticD(op, left, right);
|
| @@ -1136,8 +1156,7 @@
|
| HInstanceOfKnownGlobal* instr) {
|
| LInstanceOfKnownGlobal* result =
|
| new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
|
| - MarkAsSaveDoubles(result);
|
| - return AssignEnvironment(AssignPointerMap(DefineFixed(result, r0)));
|
| + return MarkAsCall(DefineFixed(result, r0), instr);
|
| }
|
|
|
|
|
| @@ -1193,34 +1212,29 @@
|
|
|
| LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
|
| BuiltinFunctionId op = instr->op();
|
| - LOperand* input = UseRegisterAtStart(instr->value());
|
| - LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
|
| - LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
|
| - switch (op) {
|
| - case kMathAbs:
|
| - return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
|
| - case kMathFloor:
|
| - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
|
| - case kMathSqrt:
|
| - return DefineSameAsFirst(result);
|
| - case kMathRound:
|
| - Abort("MathRound LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathPowHalf:
|
| - Abort("MathPowHalf LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathLog:
|
| - Abort("MathLog LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathCos:
|
| - Abort("MathCos LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathSin:
|
| - Abort("MathSin LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - default:
|
| - UNREACHABLE();
|
| - return NULL;
|
| + if (op == kMathLog || op == kMathSin || op == kMathCos) {
|
| + LOperand* input = UseFixedDouble(instr->value(), d2);
|
| + LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
|
| + return MarkAsCall(DefineFixedDouble(result, d2), instr);
|
| + } else {
|
| + LOperand* input = UseRegisterAtStart(instr->value());
|
| + LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
|
| + LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
|
| + switch (op) {
|
| + case kMathAbs:
|
| + return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
|
| + case kMathFloor:
|
| + return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
|
| + case kMathSqrt:
|
| + return DefineSameAsFirst(result);
|
| + case kMathRound:
|
| + return AssignEnvironment(DefineAsRegister(result));
|
| + case kMathPowHalf:
|
| + return DefineSameAsFirst(result);
|
| + default:
|
| + UNREACHABLE();
|
| + return NULL;
|
| + }
|
| }
|
| }
|
|
|
| @@ -1336,10 +1350,21 @@
|
| // when we provide a native implementation.
|
| ASSERT(instr->left()->representation().IsInteger32());
|
| ASSERT(instr->right()->representation().IsInteger32());
|
| - LOperand* value = UseFixed(instr->left(), r0);
|
| - LOperand* divisor = UseFixed(instr->right(), r1);
|
| - LInstruction* result = DefineFixed(new LModI(value, divisor), r0);
|
| - result = AssignEnvironment(AssignPointerMap(result));
|
| +
|
| + LInstruction* result;
|
| + if (instr->HasPowerOf2Divisor()) {
|
| + ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
|
| + LOperand* value = UseRegisterAtStart(instr->left());
|
| + LModI* mod = new LModI(value, UseOrConstant(instr->right()));
|
| + result = DefineSameAsFirst(mod);
|
| + result = AssignEnvironment(result);
|
| + } else {
|
| + LOperand* value = UseFixed(instr->left(), r0);
|
| + LOperand* divisor = UseFixed(instr->right(), r1);
|
| + result = DefineFixed(new LModI(value, divisor), r0);
|
| + result = AssignEnvironment(AssignPointerMap(result));
|
| + }
|
| +
|
| return result;
|
| } else if (instr->representation().IsTagged()) {
|
| return DoArithmeticT(Token::MOD, instr);
|
| @@ -1418,8 +1443,19 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoPower(HPower* instr) {
|
| - Abort("LPower instruction not implemented on ARM");
|
| - return NULL;
|
| + ASSERT(instr->representation().IsDouble());
|
| + // We call a C function for double power. It can't trigger a GC.
|
| + // We need to use fixed result register for the call.
|
| + Representation exponent_type = instr->right()->representation();
|
| + ASSERT(instr->left()->representation().IsDouble());
|
| + LOperand* left = UseFixedDouble(instr->left(), d1);
|
| + LOperand* right = exponent_type.IsDouble() ?
|
| + UseFixedDouble(instr->right(), d2) :
|
| + UseFixed(instr->right(), r0);
|
| + LPower* result = new LPower(left, right);
|
| + return MarkAsCall(DefineFixedDouble(result, d3),
|
| + instr,
|
| + CAN_DEOPTIMIZE_EAGERLY);
|
| }
|
|
|
|
|
| @@ -1491,6 +1527,15 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
|
| + HGetCachedArrayIndex* instr) {
|
| + ASSERT(instr->value()->representation().IsTagged());
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| +
|
| + return DefineAsRegister(new LGetCachedArrayIndex(value));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
|
| HHasCachedArrayIndex* instr) {
|
| ASSERT(instr->value()->representation().IsTagged());
|
| @@ -1513,9 +1558,10 @@
|
| }
|
|
|
|
|
| -LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
|
| +LInstruction* LChunkBuilder::DoExternalArrayLength(
|
| + HExternalArrayLength* instr) {
|
| LOperand* array = UseRegisterAtStart(instr->value());
|
| - return DefineAsRegister(new LPixelArrayLength(array));
|
| + return DefineAsRegister(new LExternalArrayLength(array));
|
| }
|
|
|
|
|
| @@ -1564,12 +1610,15 @@
|
| LOperand* value = UseRegister(instr->value());
|
| bool needs_check = !instr->value()->type().IsSmi();
|
| LInstruction* res = NULL;
|
| - if (needs_check) {
|
| - res = DefineSameAsFirst(new LTaggedToI(value, FixedTemp(d1)));
|
| + if (!needs_check) {
|
| + res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
|
| } else {
|
| - res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
|
| - }
|
| - if (needs_check) {
|
| + LOperand* temp1 = TempRegister();
|
| + LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
|
| + : NULL;
|
| + LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3)
|
| + : NULL;
|
| + res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
|
| res = AssignEnvironment(res);
|
| }
|
| return res;
|
| @@ -1589,7 +1638,10 @@
|
| } else {
|
| ASSERT(to.IsInteger32());
|
| LOperand* value = UseRegister(instr->value());
|
| - LDoubleToI* res = new LDoubleToI(value, TempRegister());
|
| + LDoubleToI* res =
|
| + new LDoubleToI(value,
|
| + TempRegister(),
|
| + instr->CanTruncateToInt32() ? TempRegister() : NULL);
|
| return AssignEnvironment(DefineAsRegister(res));
|
| }
|
| } else if (from.IsInteger32()) {
|
| @@ -1700,11 +1752,13 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
|
| - LOperand* context = UseTempRegister(instr->context());
|
| + LOperand* context;
|
| LOperand* value;
|
| if (instr->NeedsWriteBarrier()) {
|
| + context = UseTempRegister(instr->context());
|
| value = UseTempRegister(instr->value());
|
| } else {
|
| + context = UseRegister(instr->context());
|
| value = UseRegister(instr->value());
|
| }
|
| return new LStoreContextSlot(context, value);
|
| @@ -1737,10 +1791,10 @@
|
| }
|
|
|
|
|
| -LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
|
| - HLoadPixelArrayExternalPointer* instr) {
|
| +LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
|
| + HLoadExternalArrayPointer* instr) {
|
| LOperand* input = UseRegisterAtStart(instr->value());
|
| - return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
|
| + return DefineAsRegister(new LLoadExternalArrayPointer(input));
|
| }
|
|
|
|
|
| @@ -1797,6 +1851,20 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoStorePixelArrayElement(
|
| + HStorePixelArrayElement* instr) {
|
| + ASSERT(instr->value()->representation().IsInteger32());
|
| + ASSERT(instr->external_pointer()->representation().IsExternal());
|
| + ASSERT(instr->key()->representation().IsInteger32());
|
| +
|
| + LOperand* external_pointer = UseRegister(instr->external_pointer());
|
| + LOperand* value = UseTempRegister(instr->value()); // changed by clamp.
|
| + LOperand* key = UseRegister(instr->key());
|
| +
|
| + return new LStorePixelArrayElement(external_pointer, key, value);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
|
| LOperand* obj = UseFixed(instr->object(), r2);
|
| LOperand* key = UseFixed(instr->key(), r1);
|
| @@ -1842,6 +1910,13 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
|
| + LOperand* char_code = UseRegister(instr->value());
|
| + LStringCharFromCode* result = new LStringCharFromCode(char_code);
|
| + return AssignPointerMap(DefineAsRegister(result));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
|
| LOperand* string = UseRegisterAtStart(instr->value());
|
| return DefineAsRegister(new LStringLength(string));
|
| @@ -1902,8 +1977,10 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
|
| - // There are no real uses of the arguments object (we bail out in all other
|
| - // cases).
|
| + // There are no real uses of the arguments object.
|
| + // arguments.length and element access are supported directly on
|
| + // stack arguments, and any real arguments object use causes a bailout.
|
| + // So this value is never used.
|
| return NULL;
|
| }
|
|
|
|
|