Chromium Code Reviews| Index: src/arm/lithium-codegen-arm.cc |
| =================================================================== |
| --- src/arm/lithium-codegen-arm.cc (revision 6231) |
| +++ src/arm/lithium-codegen-arm.cc (working copy) |
| @@ -1380,15 +1380,64 @@ |
| } |
| -// Branches to a label or falls through with the answer in the z flag. Trashes |
| -// the temp registers, but not the input. Only input and temp2 may alias. |
| +// Branches to a label or falls through with the answer in the z flag. Trashes |
| +// the temp registers, but not the input. Only input and temp2 may alias. |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
input is trashed if temp2 aliases it.
Alexandre
2011/01/10 10:48:27
Indeed. Changed the code to have input and temp2 a
|
| void LCodeGen::EmitClassOfTest(Label* is_true, |
| Label* is_false, |
| Handle<String>class_name, |
| Register input, |
| Register temp, |
| Register temp2) { |
| - Abort("EmitClassOfTest unimplemented."); |
| + ASSERT(!input.is(temp)); |
| + ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. |
| + |
| + __ BranchOnSmi(input, is_false); |
| + |
| + __ CompareObjectType(input, temp, temp2, FIRST_JS_OBJECT_TYPE); |
| + __ b(lt, is_false); |
| + |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
How about just
// temp: map of input
// temp2: o
Alexandre
2011/01/10 10:48:27
Done.
|
| + // After CompareObjectType: |
| + // - Input's map is in temp. |
| + // - Input's type is in temp2. |
| + |
| + // Functions have class 'Function'. |
| + __ cmp(temp2, Operand(JS_FUNCTION_TYPE)); |
| + if (class_name->IsEqualTo(CStrVector("Function"))) { |
| + __ b(eq, is_true); |
| + } else { |
| + __ b(eq, is_false); |
| + } |
| + |
| + // Check if the constructor in the map is a function. |
| + __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset)); |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
After this
// temp: constructor
Alexandre
2011/01/10 10:48:27
Done.
|
| + |
| + // As long as JS_FUNCTION_TYPE is the last instance type and it is |
| + // right after LAST_JS_OBJECT_TYPE, we can avoid checking for |
| + // LAST_JS_OBJECT_TYPE. |
| + ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| + ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); |
| + |
| + // Objects with a non-function constructor have class 'Object'. |
| + __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE); |
| + if (class_name->IsEqualTo(CStrVector("Object"))) { |
| + __ b(ne, is_true); |
| + } else { |
| + __ b(ne, is_false); |
| + } |
| + |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
Change comment to
// Get the instance class name
Alexandre
2011/01/10 10:48:27
Done.
|
| + // temp now contains the constructor function. Grab the |
| + // instance class name from there. |
| + __ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); |
| + __ ldr(temp, FieldMemOperand(temp, |
| + SharedFunctionInfo::kInstanceClassNameOffset)); |
| + // The class name we are testing against is a symbol because it's a literal. |
| + // The name in the constructor is a symbol because of the way the context is |
| + // booted. This routine isn't expected to work for random API-created |
| + // classes and it doesn't have to because you can't access it with natives |
| + // syntax. Since both sides are symbols it is sufficient to use an identity |
| + // comparison. |
| + __ cmp(temp, Operand(class_name)); |
| + // End with the answer in the z flag. |
| } |
| @@ -1398,7 +1447,26 @@ |
| void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| - Abort("DoClassOfTestAndBranch unimplemented."); |
| + Register input = ToRegister(instr->input()); |
| + Register temp = ToRegister(instr->temporary()); |
| + Register temp2 = ToRegister(instr->temporary2()); |
| + if (input.is(temp)) { |
| + // Swap. |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
There is a Swap instruction in the macro assembler
Alexandre
2011/01/10 10:48:27
Removed. Not needed anymore, as all these register
|
| + Register swapper = temp; |
| + temp = temp2; |
| + temp2 = swapper; |
| + } |
| + Handle<String> class_name = instr->hydrogen()->class_name(); |
| + |
| + int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| + int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| + |
| + Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| + Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| + |
| + EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| + |
| + EmitBranch(true_block, false_block, eq); |
| } |
| @@ -1784,12 +1852,42 @@ |
| void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| - Abort("DoMathFloor unimplemented."); |
| + DoubleRegister input_reg = ToDoubleRegister(instr->input()); |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
input_reg -> input?
|
| + SwVfpRegister single_precision_scratch = s0; |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
Please add double_scratch0() and single_scratch0()
|
| + Register result = ToRegister(instr->result()); |
| + Register scratch = scratch0(); |
| + |
| + // Set custom FPCSR: |
| + // - Set rounding mode to "Round towards Minus Infinity" |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
No need to refer to specific bit numbers in the co
|
| + // (ie bits [23:22] = 0b10). |
| + // - Clear vfp cumulative exception flags (bits [3:0]). |
| + // - Make sure Flush-to-zero mode control bit is unset (bit 22). |
| + __ vmrs(scratch); |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
Don't we need to backup and restore FPSCR here? Th
|
| + __ bic(scratch, scratch, |
| + Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); |
| + __ orr(scratch, scratch, Operand(kVFPRoundToMinusInfinityBits)); |
| + __ vmsr(scratch); |
| + |
| + // Convert the argument to an integer. |
| + __ vcvt_s32_f64(single_precision_scratch, |
| + input_reg, |
| + Assembler::FPSCRRounding, |
| + al); |
| + |
| + // Retrieve FPSCR and check for vfp exceptions. |
| + __ vmrs(scratch); |
| + __ tst(scratch, Operand(kVFPExceptionMask)); |
| + DeoptimizeIf(ne, instr->environment()); |
| + |
| + // Move the result back to general purpose register r0. |
| + __ vmov(result, single_precision_scratch); |
| } |
| void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| - Abort("DoMathSqrt unimplemented."); |
| + DoubleRegister input_reg = ToDoubleRegister(instr->input()); |
|
Søren Thygesen Gjesse
2011/01/10 09:56:08
input_reg -> input?
Alexandre
2011/01/10 10:48:27
Done.
|
| + ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| + __ vsqrt(input_reg, input_reg); |
| } |