| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1668 AllowDeferredHandleDereference smi_check; | 1668 AllowDeferredHandleDereference smi_check; |
| 1669 if (value->IsSmi()) { | 1669 if (value->IsSmi()) { |
| 1670 __ li(ToRegister(instr->result()), Operand(value)); | 1670 __ li(ToRegister(instr->result()), Operand(value)); |
| 1671 } else { | 1671 } else { |
| 1672 __ LoadHeapObject(ToRegister(instr->result()), | 1672 __ LoadHeapObject(ToRegister(instr->result()), |
| 1673 Handle<HeapObject>::cast(value)); | 1673 Handle<HeapObject>::cast(value)); |
| 1674 } | 1674 } |
| 1675 } | 1675 } |
| 1676 | 1676 |
| 1677 | 1677 |
| 1678 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { | |
| 1679 Register result = ToRegister(instr->result()); | |
| 1680 Register array = ToRegister(instr->value()); | |
| 1681 __ lw(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); | |
| 1682 } | |
| 1683 | |
| 1684 | |
| 1685 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1678 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1686 Register result = ToRegister(instr->result()); | 1679 Register result = ToRegister(instr->result()); |
| 1687 Register map = ToRegister(instr->value()); | 1680 Register map = ToRegister(instr->value()); |
| 1688 __ EnumLength(result, map); | 1681 __ EnumLength(result, map); |
| 1689 } | 1682 } |
| 1690 | 1683 |
| 1691 | 1684 |
| 1692 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1685 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
| 1693 Register result = ToRegister(instr->result()); | 1686 Register result = ToRegister(instr->result()); |
| 1694 Register input = ToRegister(instr->value()); | 1687 Register input = ToRegister(instr->value()); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1971 int LCodeGen::GetNextEmittedBlock() const { | 1964 int LCodeGen::GetNextEmittedBlock() const { |
| 1972 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 1965 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
| 1973 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 1966 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
| 1974 } | 1967 } |
| 1975 return -1; | 1968 return -1; |
| 1976 } | 1969 } |
| 1977 | 1970 |
| 1978 template<class InstrType> | 1971 template<class InstrType> |
| 1979 void LCodeGen::EmitBranch(InstrType instr, | 1972 void LCodeGen::EmitBranch(InstrType instr, |
| 1980 Condition cc, Register src1, const Operand& src2) { | 1973 Condition cc, Register src1, const Operand& src2) { |
| 1974 int left_block = instr->TrueDestination(chunk_); |
| 1981 int right_block = instr->FalseDestination(chunk_); | 1975 int right_block = instr->FalseDestination(chunk_); |
| 1982 int left_block = instr->TrueDestination(chunk_); | |
| 1983 | 1976 |
| 1984 int next_block = GetNextEmittedBlock(); | 1977 int next_block = GetNextEmittedBlock(); |
| 1985 if (right_block == left_block) { | 1978 if (right_block == left_block || cc == al) { |
| 1986 EmitGoto(left_block); | 1979 EmitGoto(left_block); |
| 1987 } else if (left_block == next_block) { | 1980 } else if (left_block == next_block) { |
| 1988 __ Branch(chunk_->GetAssemblyLabel(right_block), | 1981 __ Branch(chunk_->GetAssemblyLabel(right_block), |
| 1989 NegateCondition(cc), src1, src2); | 1982 NegateCondition(cc), src1, src2); |
| 1990 } else if (right_block == next_block) { | 1983 } else if (right_block == next_block) { |
| 1991 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); | 1984 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); |
| 1992 } else { | 1985 } else { |
| 1993 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); | 1986 __ Branch(chunk_->GetAssemblyLabel(left_block), cc, src1, src2); |
| 1994 __ Branch(chunk_->GetAssemblyLabel(right_block)); | 1987 __ Branch(chunk_->GetAssemblyLabel(right_block)); |
| 1995 } | 1988 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2015 __ Branch(chunk_->GetAssemblyLabel(right_block)); | 2008 __ Branch(chunk_->GetAssemblyLabel(right_block)); |
| 2016 } | 2009 } |
| 2017 } | 2010 } |
| 2018 | 2011 |
| 2019 | 2012 |
| 2020 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2013 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 2021 __ stop("LDebugBreak"); | 2014 __ stop("LDebugBreak"); |
| 2022 } | 2015 } |
| 2023 | 2016 |
| 2024 | 2017 |
| 2018 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 2019 Representation r = instr->hydrogen()->value()->representation(); |
| 2020 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 2021 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); |
| 2022 } else { |
| 2023 ASSERT(r.IsTagged()); |
| 2024 Register reg = ToRegister(instr->value()); |
| 2025 HType type = instr->hydrogen()->value()->type(); |
| 2026 if (type.IsTaggedNumber()) { |
| 2027 EmitBranch(instr, al, zero_reg, Operand(zero_reg)); |
| 2028 } |
| 2029 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2030 __ lw(scratch0(), FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2031 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 2032 EmitBranch(instr, eq, scratch0(), Operand(at)); |
| 2033 } |
| 2034 } |
| 2035 |
| 2036 |
| 2025 void LCodeGen::DoBranch(LBranch* instr) { | 2037 void LCodeGen::DoBranch(LBranch* instr) { |
| 2026 Representation r = instr->hydrogen()->value()->representation(); | 2038 Representation r = instr->hydrogen()->value()->representation(); |
| 2027 if (r.IsInteger32() || r.IsSmi()) { | 2039 if (r.IsInteger32() || r.IsSmi()) { |
| 2028 ASSERT(!info()->IsStub()); | 2040 ASSERT(!info()->IsStub()); |
| 2029 Register reg = ToRegister(instr->value()); | 2041 Register reg = ToRegister(instr->value()); |
| 2030 EmitBranch(instr, ne, reg, Operand(zero_reg)); | 2042 EmitBranch(instr, ne, reg, Operand(zero_reg)); |
| 2031 } else if (r.IsDouble()) { | 2043 } else if (r.IsDouble()) { |
| 2032 ASSERT(!info()->IsStub()); | 2044 ASSERT(!info()->IsStub()); |
| 2033 DoubleRegister reg = ToDoubleRegister(instr->value()); | 2045 DoubleRegister reg = ToDoubleRegister(instr->value()); |
| 2034 // Test the double value. Zero and NaN are false. | 2046 // Test the double value. Zero and NaN are false. |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2183 break; | 2195 break; |
| 2184 case Token::IN: | 2196 case Token::IN: |
| 2185 case Token::INSTANCEOF: | 2197 case Token::INSTANCEOF: |
| 2186 default: | 2198 default: |
| 2187 UNREACHABLE(); | 2199 UNREACHABLE(); |
| 2188 } | 2200 } |
| 2189 return cond; | 2201 return cond; |
| 2190 } | 2202 } |
| 2191 | 2203 |
| 2192 | 2204 |
| 2193 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2205 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { |
| 2194 LOperand* left = instr->left(); | 2206 LOperand* left = instr->left(); |
| 2195 LOperand* right = instr->right(); | 2207 LOperand* right = instr->right(); |
| 2196 Condition cond = TokenToCondition(instr->op(), false); | 2208 Condition cond = TokenToCondition(instr->op(), false); |
| 2197 | 2209 |
| 2198 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2210 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 2199 // We can statically evaluate the comparison. | 2211 // We can statically evaluate the comparison. |
| 2200 double left_val = ToDouble(LConstantOperand::cast(left)); | 2212 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 2201 double right_val = ToDouble(LConstantOperand::cast(right)); | 2213 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 2202 int next_block = EvalComparison(instr->op(), left_val, right_val) ? | 2214 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
| 2203 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); | 2215 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
| (...skipping 1156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3360 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); | 3372 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 3361 __ Branch(&receiver_ok); | 3373 __ Branch(&receiver_ok); |
| 3362 | 3374 |
| 3363 __ bind(&global_object); | 3375 __ bind(&global_object); |
| 3364 __ lw(receiver, GlobalObjectOperand()); | 3376 __ lw(receiver, GlobalObjectOperand()); |
| 3365 __ lw(receiver, | 3377 __ lw(receiver, |
| 3366 FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); | 3378 FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); |
| 3367 __ bind(&receiver_ok); | 3379 __ bind(&receiver_ok); |
| 3368 } | 3380 } |
| 3369 | 3381 |
| 3382 |
| 3370 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3383 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 3371 Register receiver = ToRegister(instr->receiver()); | 3384 Register receiver = ToRegister(instr->receiver()); |
| 3372 Register function = ToRegister(instr->function()); | 3385 Register function = ToRegister(instr->function()); |
| 3373 Register length = ToRegister(instr->length()); | 3386 Register length = ToRegister(instr->length()); |
| 3374 Register elements = ToRegister(instr->elements()); | 3387 Register elements = ToRegister(instr->elements()); |
| 3375 Register scratch = scratch0(); | 3388 Register scratch = scratch0(); |
| 3376 ASSERT(receiver.is(a0)); // Used for parameter count. | 3389 ASSERT(receiver.is(a0)); // Used for parameter count. |
| 3377 ASSERT(function.is(a1)); // Required by InvokeFunction. | 3390 ASSERT(function.is(a1)); // Required by InvokeFunction. |
| 3378 ASSERT(ToRegister(instr->result()).is(v0)); | 3391 ASSERT(ToRegister(instr->result()).is(v0)); |
| 3379 | 3392 |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3886 // 0x41300000 is the top half of 1.0 x 2^20 as a double. | 3899 // 0x41300000 is the top half of 1.0 x 2^20 as a double. |
| 3887 __ li(a2, Operand(0x41300000)); | 3900 __ li(a2, Operand(0x41300000)); |
| 3888 // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU. | 3901 // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU. |
| 3889 __ Move(f12, v0, a2); | 3902 __ Move(f12, v0, a2); |
| 3890 // Move 0x4130000000000000 to FPU. | 3903 // Move 0x4130000000000000 to FPU. |
| 3891 __ Move(f14, zero_reg, a2); | 3904 __ Move(f14, zero_reg, a2); |
| 3892 // Subtract to get the result. | 3905 // Subtract to get the result. |
| 3893 __ sub_d(f0, f12, f14); | 3906 __ sub_d(f0, f12, f14); |
| 3894 } | 3907 } |
| 3895 | 3908 |
| 3909 |
| 3896 void LCodeGen::DoDeferredRandom(LRandom* instr) { | 3910 void LCodeGen::DoDeferredRandom(LRandom* instr) { |
| 3897 __ PrepareCallCFunction(1, scratch0()); | 3911 __ PrepareCallCFunction(1, scratch0()); |
| 3898 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); | 3912 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
| 3899 // Return value is in v0. | 3913 // Return value is in v0. |
| 3900 } | 3914 } |
| 3901 | 3915 |
| 3902 | 3916 |
| 3903 void LCodeGen::DoMathExp(LMathExp* instr) { | 3917 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 3904 DoubleRegister input = ToDoubleRegister(instr->value()); | 3918 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3905 DoubleRegister result = ToDoubleRegister(instr->result()); | 3919 DoubleRegister result = ToDoubleRegister(instr->result()); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4042 } | 4056 } |
| 4043 | 4057 |
| 4044 | 4058 |
| 4045 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4059 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 4046 ASSERT(ToRegister(instr->constructor()).is(a1)); | 4060 ASSERT(ToRegister(instr->constructor()).is(a1)); |
| 4047 ASSERT(ToRegister(instr->result()).is(v0)); | 4061 ASSERT(ToRegister(instr->result()).is(v0)); |
| 4048 | 4062 |
| 4049 __ li(a0, Operand(instr->arity())); | 4063 __ li(a0, Operand(instr->arity())); |
| 4050 __ li(a2, Operand(instr->hydrogen()->property_cell())); | 4064 __ li(a2, Operand(instr->hydrogen()->property_cell())); |
| 4051 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4065 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 4052 bool disable_allocation_sites = | 4066 AllocationSiteOverrideMode override_mode = |
| 4053 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE); | 4067 (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 4068 ? DISABLE_ALLOCATION_SITES |
| 4069 : DONT_OVERRIDE; |
| 4070 ContextCheckMode context_mode = CONTEXT_CHECK_NOT_REQUIRED; |
| 4054 | 4071 |
| 4055 if (instr->arity() == 0) { | 4072 if (instr->arity() == 0) { |
| 4056 ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites); | 4073 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); |
| 4057 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4074 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4058 } else if (instr->arity() == 1) { | 4075 } else if (instr->arity() == 1) { |
| 4059 Label done; | 4076 Label done; |
| 4060 if (IsFastPackedElementsKind(kind)) { | 4077 if (IsFastPackedElementsKind(kind)) { |
| 4061 Label packed_case; | 4078 Label packed_case; |
| 4062 // We might need a change here, | 4079 // We might need a change here, |
| 4063 // look at the first argument. | 4080 // look at the first argument. |
| 4064 __ lw(t1, MemOperand(sp, 0)); | 4081 __ lw(t1, MemOperand(sp, 0)); |
| 4065 __ Branch(&packed_case, eq, t1, Operand(zero_reg)); | 4082 __ Branch(&packed_case, eq, t1, Operand(zero_reg)); |
| 4066 | 4083 |
| 4067 ElementsKind holey_kind = GetHoleyElementsKind(kind); | 4084 ElementsKind holey_kind = GetHoleyElementsKind(kind); |
| 4068 ArraySingleArgumentConstructorStub stub(holey_kind, | 4085 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, |
| 4069 disable_allocation_sites); | 4086 override_mode); |
| 4070 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4087 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4071 __ jmp(&done); | 4088 __ jmp(&done); |
| 4072 __ bind(&packed_case); | 4089 __ bind(&packed_case); |
| 4073 } | 4090 } |
| 4074 | 4091 |
| 4075 ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites); | 4092 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); |
| 4076 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4093 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4077 __ bind(&done); | 4094 __ bind(&done); |
| 4078 } else { | 4095 } else { |
| 4079 ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites); | 4096 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); |
| 4080 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4097 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4081 } | 4098 } |
| 4082 } | 4099 } |
| 4083 | 4100 |
| 4084 | 4101 |
| 4085 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 4102 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 4086 CallRuntime(instr->function(), instr->arity(), instr); | 4103 CallRuntime(instr->function(), instr->arity(), instr); |
| 4087 } | 4104 } |
| 4088 | 4105 |
| 4089 | 4106 |
| (...skipping 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5904 __ Subu(scratch, result, scratch); | 5921 __ Subu(scratch, result, scratch); |
| 5905 __ lw(result, FieldMemOperand(scratch, | 5922 __ lw(result, FieldMemOperand(scratch, |
| 5906 FixedArray::kHeaderSize - kPointerSize)); | 5923 FixedArray::kHeaderSize - kPointerSize)); |
| 5907 __ bind(&done); | 5924 __ bind(&done); |
| 5908 } | 5925 } |
| 5909 | 5926 |
| 5910 | 5927 |
| 5911 #undef __ | 5928 #undef __ |
| 5912 | 5929 |
| 5913 } } // namespace v8::internal | 5930 } } // namespace v8::internal |
| OLD | NEW |