Chromium Code Reviews| 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 2139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2150 __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); | 2150 __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); |
| 2151 } else if (right_block == next_block) { | 2151 } else if (right_block == next_block) { |
| 2152 __ b(cc, chunk_->GetAssemblyLabel(left_block)); | 2152 __ b(cc, chunk_->GetAssemblyLabel(left_block)); |
| 2153 } else { | 2153 } else { |
| 2154 __ b(cc, chunk_->GetAssemblyLabel(left_block)); | 2154 __ b(cc, chunk_->GetAssemblyLabel(left_block)); |
| 2155 __ b(chunk_->GetAssemblyLabel(right_block)); | 2155 __ b(chunk_->GetAssemblyLabel(right_block)); |
| 2156 } | 2156 } |
| 2157 } | 2157 } |
| 2158 | 2158 |
| 2159 | 2159 |
| 2160 template<class InstrType> | |
| 2161 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { | |
|
Rodolph Perfetta
2013/08/13 15:08:14
cc is actually a valid ARM condition code (carry c
Toon Verwaest
2013/08/13 15:16:50
I used the same signature as the function above (E
Rodolph Perfetta
2013/08/13 15:22:02
It would be better to change it above too. If this
| |
| 2162 int false_block = instr->FalseDestination(chunk_); | |
| 2163 __ b(cc, chunk_->GetAssemblyLabel(false_block)); | |
| 2164 } | |
| 2165 | |
| 2166 | |
| 2160 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2167 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 2161 __ stop("LBreak"); | 2168 __ stop("LBreak"); |
| 2162 } | 2169 } |
| 2163 | 2170 |
| 2164 | 2171 |
| 2165 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { | 2172 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 2166 Representation r = instr->hydrogen()->value()->representation(); | 2173 Representation r = instr->hydrogen()->value()->representation(); |
| 2167 if (r.IsSmiOrInteger32() || r.IsDouble()) { | 2174 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 2168 EmitBranch(instr, al); | 2175 EmitBranch(instr, al); |
| 2169 } else { | 2176 } else { |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2405 | 2412 |
| 2406 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2413 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2407 Register left = ToRegister(instr->left()); | 2414 Register left = ToRegister(instr->left()); |
| 2408 Register right = ToRegister(instr->right()); | 2415 Register right = ToRegister(instr->right()); |
| 2409 | 2416 |
| 2410 __ cmp(left, Operand(right)); | 2417 __ cmp(left, Operand(right)); |
| 2411 EmitBranch(instr, eq); | 2418 EmitBranch(instr, eq); |
| 2412 } | 2419 } |
| 2413 | 2420 |
| 2414 | 2421 |
| 2422 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { | |
| 2423 if (instr->hydrogen()->representation().IsTagged()) { | |
| 2424 Register input_reg = ToRegister(instr->object()); | |
| 2425 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); | |
| 2426 __ mov(ip, Operand(Handle<Object>(cell))); | |
|
Rodolph Perfetta
2013/08/13 15:08:14
Shouldn't this be: mov(ip, factory()->the_hole_val
Toon Verwaest
2013/08/13 15:16:50
Makes a lot of sense. Wrongly copy pasted from bel
| |
| 2427 __ cmp(input_reg, ip); | |
| 2428 EmitBranch(instr, eq); | |
| 2429 return; | |
| 2430 } | |
| 2431 | |
| 2432 DwVfpRegister input_reg = ToDoubleRegister(instr->object()); | |
| 2433 __ VFPCompareAndSetFlags(input_reg, input_reg); | |
| 2434 EmitFalseBranch(instr, vc); | |
| 2435 | |
| 2436 Register scratch = scratch0(); | |
| 2437 __ VmovHigh(scratch, input_reg); | |
| 2438 __ cmp(scratch, Operand(kHoleNanUpper32)); | |
| 2439 EmitBranch(instr, eq); | |
| 2440 } | |
| 2441 | |
| 2442 | |
| 2415 Condition LCodeGen::EmitIsObject(Register input, | 2443 Condition LCodeGen::EmitIsObject(Register input, |
| 2416 Register temp1, | 2444 Register temp1, |
| 2417 Label* is_not_object, | 2445 Label* is_not_object, |
| 2418 Label* is_object) { | 2446 Label* is_object) { |
| 2419 Register temp2 = scratch0(); | 2447 Register temp2 = scratch0(); |
| 2420 __ JumpIfSmi(input, is_not_object); | 2448 __ JumpIfSmi(input, is_not_object); |
| 2421 | 2449 |
| 2422 __ LoadRoot(temp2, Heap::kNullValueRootIndex); | 2450 __ LoadRoot(temp2, Heap::kNullValueRootIndex); |
| 2423 __ cmp(input, temp2); | 2451 __ cmp(input, temp2); |
| 2424 __ b(eq, is_object); | 2452 __ b(eq, is_object); |
| (...skipping 2394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4819 private: | 4847 private: |
| 4820 LNumberTagD* instr_; | 4848 LNumberTagD* instr_; |
| 4821 }; | 4849 }; |
| 4822 | 4850 |
| 4823 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | 4851 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); |
| 4824 Register scratch = scratch0(); | 4852 Register scratch = scratch0(); |
| 4825 Register reg = ToRegister(instr->result()); | 4853 Register reg = ToRegister(instr->result()); |
| 4826 Register temp1 = ToRegister(instr->temp()); | 4854 Register temp1 = ToRegister(instr->temp()); |
| 4827 Register temp2 = ToRegister(instr->temp2()); | 4855 Register temp2 = ToRegister(instr->temp2()); |
| 4828 | 4856 |
| 4829 bool convert_hole = false; | |
| 4830 HValue* change_input = instr->hydrogen()->value(); | |
| 4831 if (change_input->IsLoadKeyed()) { | |
| 4832 HLoadKeyed* load = HLoadKeyed::cast(change_input); | |
| 4833 convert_hole = load->UsesMustHandleHole(); | |
| 4834 } | |
| 4835 | |
| 4836 Label no_special_nan_handling; | |
| 4837 Label done; | |
| 4838 if (convert_hole) { | |
| 4839 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | |
| 4840 __ VFPCompareAndSetFlags(input_reg, input_reg); | |
| 4841 __ b(vc, &no_special_nan_handling); | |
| 4842 __ VmovHigh(scratch, input_reg); | |
| 4843 __ cmp(scratch, Operand(kHoleNanUpper32)); | |
| 4844 // If not the hole NaN, force the NaN to be canonical. | |
| 4845 __ VFPCanonicalizeNaN(input_reg, ne); | |
| 4846 __ b(ne, &no_special_nan_handling); | |
| 4847 __ Move(reg, factory()->the_hole_value()); | |
| 4848 __ b(&done); | |
| 4849 } | |
| 4850 | |
| 4851 __ bind(&no_special_nan_handling); | |
| 4852 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4857 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 4853 if (FLAG_inline_new) { | 4858 if (FLAG_inline_new) { |
| 4854 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4859 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
| 4855 // We want the untagged address first for performance | 4860 // We want the untagged address first for performance |
| 4856 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), | 4861 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(), |
| 4857 DONT_TAG_RESULT); | 4862 DONT_TAG_RESULT); |
| 4858 } else { | 4863 } else { |
| 4859 __ jmp(deferred->entry()); | 4864 __ jmp(deferred->entry()); |
| 4860 } | 4865 } |
| 4861 __ bind(deferred->exit()); | 4866 __ bind(deferred->exit()); |
| 4862 __ vstr(input_reg, reg, HeapNumber::kValueOffset); | 4867 __ vstr(input_reg, reg, HeapNumber::kValueOffset); |
| 4863 // Now that we have finished with the object's real address tag it | 4868 // Now that we have finished with the object's real address tag it |
| 4864 __ add(reg, reg, Operand(kHeapObjectTag)); | 4869 __ add(reg, reg, Operand(kHeapObjectTag)); |
| 4865 __ bind(&done); | |
| 4866 } | 4870 } |
| 4867 | 4871 |
| 4868 | 4872 |
| 4869 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4873 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4870 // TODO(3095996): Get rid of this. For now, we need to make the | 4874 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4871 // result register contain a valid pointer because it is already | 4875 // result register contain a valid pointer because it is already |
| 4872 // contained in the register pointer map. | 4876 // contained in the register pointer map. |
| 4873 Register reg = ToRegister(instr->result()); | 4877 Register reg = ToRegister(instr->result()); |
| 4874 __ mov(reg, Operand::Zero()); | 4878 __ mov(reg, Operand::Zero()); |
| 4875 | 4879 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 4895 __ SmiUntag(result, input, SetCC); | 4899 __ SmiUntag(result, input, SetCC); |
| 4896 DeoptimizeIf(cs, instr->environment()); | 4900 DeoptimizeIf(cs, instr->environment()); |
| 4897 } else { | 4901 } else { |
| 4898 __ SmiUntag(result, input); | 4902 __ SmiUntag(result, input); |
| 4899 } | 4903 } |
| 4900 } | 4904 } |
| 4901 | 4905 |
| 4902 | 4906 |
| 4903 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4907 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 4904 DwVfpRegister result_reg, | 4908 DwVfpRegister result_reg, |
| 4905 bool allow_undefined_as_nan, | 4909 bool can_convert_undefined_to_nan, |
| 4906 bool deoptimize_on_minus_zero, | 4910 bool deoptimize_on_minus_zero, |
| 4907 LEnvironment* env, | 4911 LEnvironment* env, |
| 4908 NumberUntagDMode mode) { | 4912 NumberUntagDMode mode) { |
| 4909 Register scratch = scratch0(); | 4913 Register scratch = scratch0(); |
| 4910 SwVfpRegister flt_scratch = double_scratch0().low(); | 4914 SwVfpRegister flt_scratch = double_scratch0().low(); |
| 4911 ASSERT(!result_reg.is(double_scratch0())); | 4915 ASSERT(!result_reg.is(double_scratch0())); |
| 4912 | 4916 |
| 4913 Label load_smi, heap_number, done; | 4917 Label load_smi, heap_number, done; |
| 4914 | 4918 |
| 4915 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > | 4919 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4916 NUMBER_CANDIDATE_IS_ANY_TAGGED); | |
| 4917 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { | |
| 4918 // Smi check. | 4920 // Smi check. |
| 4919 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4921 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4920 | 4922 |
| 4921 // Heap number map check. | 4923 // Heap number map check. |
| 4922 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4924 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4923 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4925 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 4924 __ cmp(scratch, Operand(ip)); | 4926 __ cmp(scratch, Operand(ip)); |
| 4925 if (!allow_undefined_as_nan) { | 4927 if (!can_convert_undefined_to_nan) { |
| 4926 DeoptimizeIf(ne, env); | 4928 DeoptimizeIf(ne, env); |
| 4927 } else { | 4929 } else { |
| 4928 Label heap_number, convert; | 4930 Label heap_number, convert; |
| 4929 __ b(eq, &heap_number); | 4931 __ b(eq, &heap_number); |
| 4930 | 4932 |
| 4931 // Convert undefined (and hole) to NaN. | 4933 // Convert undefined (and hole) to NaN. |
| 4932 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4934 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 4933 __ cmp(input_reg, Operand(ip)); | 4935 __ cmp(input_reg, Operand(ip)); |
| 4934 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) { | |
| 4935 __ b(eq, &convert); | |
| 4936 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
| 4937 __ cmp(input_reg, Operand(ip)); | |
| 4938 } | |
| 4939 DeoptimizeIf(ne, env); | 4936 DeoptimizeIf(ne, env); |
| 4940 | 4937 |
| 4941 __ bind(&convert); | 4938 __ bind(&convert); |
| 4942 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4939 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
| 4943 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); | 4940 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); |
| 4944 __ jmp(&done); | 4941 __ jmp(&done); |
| 4945 | 4942 |
| 4946 __ bind(&heap_number); | 4943 __ bind(&heap_number); |
| 4947 } | 4944 } |
| 4948 // Heap number to double register conversion. | 4945 // Heap number to double register conversion. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5069 | 5066 |
| 5070 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 5067 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 5071 LOperand* input = instr->value(); | 5068 LOperand* input = instr->value(); |
| 5072 ASSERT(input->IsRegister()); | 5069 ASSERT(input->IsRegister()); |
| 5073 LOperand* result = instr->result(); | 5070 LOperand* result = instr->result(); |
| 5074 ASSERT(result->IsDoubleRegister()); | 5071 ASSERT(result->IsDoubleRegister()); |
| 5075 | 5072 |
| 5076 Register input_reg = ToRegister(input); | 5073 Register input_reg = ToRegister(input); |
| 5077 DwVfpRegister result_reg = ToDoubleRegister(result); | 5074 DwVfpRegister result_reg = ToDoubleRegister(result); |
| 5078 | 5075 |
| 5079 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED; | |
| 5080 HValue* value = instr->hydrogen()->value(); | 5076 HValue* value = instr->hydrogen()->value(); |
| 5081 if (value->type().IsSmi()) { | 5077 NumberUntagDMode mode = value->representation().IsSmi() |
| 5082 mode = NUMBER_CANDIDATE_IS_SMI; | 5078 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 5083 } else if (value->IsLoadKeyed()) { | |
| 5084 HLoadKeyed* load = HLoadKeyed::cast(value); | |
| 5085 if (load->UsesMustHandleHole()) { | |
| 5086 if (load->hole_mode() == ALLOW_RETURN_HOLE) { | |
| 5087 mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE; | |
| 5088 } | |
| 5089 } | |
| 5090 } | |
| 5091 | 5079 |
| 5092 EmitNumberUntagD(input_reg, result_reg, | 5080 EmitNumberUntagD(input_reg, result_reg, |
| 5093 instr->hydrogen()->allow_undefined_as_nan(), | 5081 instr->hydrogen()->can_convert_undefined_to_nan(), |
| 5094 instr->hydrogen()->deoptimize_on_minus_zero(), | 5082 instr->hydrogen()->deoptimize_on_minus_zero(), |
| 5095 instr->environment(), | 5083 instr->environment(), |
| 5096 mode); | 5084 mode); |
| 5097 } | 5085 } |
| 5098 | 5086 |
| 5099 | 5087 |
| 5100 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5088 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5101 Register result_reg = ToRegister(instr->result()); | 5089 Register result_reg = ToRegister(instr->result()); |
| 5102 Register scratch1 = scratch0(); | 5090 Register scratch1 = scratch0(); |
| 5103 Register scratch2 = ToRegister(instr->temp()); | 5091 Register scratch2 = ToRegister(instr->temp()); |
| (...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5856 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5844 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5857 __ ldr(result, FieldMemOperand(scratch, | 5845 __ ldr(result, FieldMemOperand(scratch, |
| 5858 FixedArray::kHeaderSize - kPointerSize)); | 5846 FixedArray::kHeaderSize - kPointerSize)); |
| 5859 __ bind(&done); | 5847 __ bind(&done); |
| 5860 } | 5848 } |
| 5861 | 5849 |
| 5862 | 5850 |
| 5863 #undef __ | 5851 #undef __ |
| 5864 | 5852 |
| 5865 } } // namespace v8::internal | 5853 } } // namespace v8::internal |
| OLD | NEW |