| 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 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 ASSERT(environment->HasBeenRegistered()); | 762 ASSERT(environment->HasBeenRegistered()); |
| 763 int id = environment->deoptimization_index(); | 763 int id = environment->deoptimization_index(); |
| 764 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 764 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
| 765 Address entry = | 765 Address entry = |
| 766 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 766 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 767 if (entry == NULL) { | 767 if (entry == NULL) { |
| 768 Abort(kBailoutWasNotPrepared); | 768 Abort(kBailoutWasNotPrepared); |
| 769 return; | 769 return; |
| 770 } | 770 } |
| 771 | 771 |
| 772 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. | 772 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { |
| 773 if (FLAG_deopt_every_n_times == 1 && | 773 Register scratch = scratch0(); |
| 774 !info()->IsStub() && | 774 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); |
| 775 info()->opt_count() == id) { | 775 |
| 776 ASSERT(frame_is_built_); | 776 // Store the condition on the stack if necessary |
| 777 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 777 if (condition != al) { |
| 778 return; | 778 __ mov(scratch, Operand::Zero(), LeaveCC, NegateCondition(condition)); |
| 779 __ mov(scratch, Operand(1), LeaveCC, condition); |
| 780 __ push(scratch); |
| 781 } |
| 782 |
| 783 __ push(r1); |
| 784 __ mov(scratch, Operand(count)); |
| 785 __ ldr(r1, MemOperand(scratch)); |
| 786 __ sub(r1, r1, Operand(1), SetCC); |
| 787 __ movw(r1, FLAG_deopt_every_n_times, eq); |
| 788 __ str(r1, MemOperand(scratch)); |
| 789 __ pop(r1); |
| 790 |
| 791 if (condition != al) { |
| 792 // Clean up the stack before the deoptimizer call |
| 793 __ pop(scratch); |
| 794 } |
| 795 |
| 796 __ Call(entry, RelocInfo::RUNTIME_ENTRY, eq); |
| 797 |
| 798 // 'Restore' the condition in a slightly hacky way. (It would be better |
| 799 // to use 'msr' and 'mrs' instructions here, but they are not supported by |
| 800 // our ARM simulator). |
| 801 if (condition != al) { |
| 802 condition = ne; |
| 803 __ cmp(scratch, Operand::Zero()); |
| 804 } |
| 779 } | 805 } |
| 780 | 806 |
| 781 if (info()->ShouldTrapOnDeopt()) { | 807 if (info()->ShouldTrapOnDeopt()) { |
| 782 __ stop("trap_on_deopt", condition); | 808 __ stop("trap_on_deopt", condition); |
| 783 } | 809 } |
| 784 | 810 |
| 785 ASSERT(info()->IsStub() || frame_is_built_); | 811 ASSERT(info()->IsStub() || frame_is_built_); |
| 786 if (condition == al && frame_is_built_) { | 812 if (condition == al && frame_is_built_) { |
| 787 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 813 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 788 } else { | 814 } else { |
| (...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1941 if (encoding == String::ONE_BYTE_ENCODING) { | 1967 if (encoding == String::ONE_BYTE_ENCODING) { |
| 1942 __ add(scratch, string, Operand(ToRegister(index))); | 1968 __ add(scratch, string, Operand(ToRegister(index))); |
| 1943 } else { | 1969 } else { |
| 1944 STATIC_ASSERT(kUC16Size == 2); | 1970 STATIC_ASSERT(kUC16Size == 2); |
| 1945 __ add(scratch, string, Operand(ToRegister(index), LSL, 1)); | 1971 __ add(scratch, string, Operand(ToRegister(index), LSL, 1)); |
| 1946 } | 1972 } |
| 1947 return FieldMemOperand(scratch, SeqString::kHeaderSize); | 1973 return FieldMemOperand(scratch, SeqString::kHeaderSize); |
| 1948 } | 1974 } |
| 1949 | 1975 |
| 1950 | 1976 |
| 1977 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { |
| 1978 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 1979 Register string = ToRegister(instr->string()); |
| 1980 Register result = ToRegister(instr->result()); |
| 1981 |
| 1982 if (FLAG_debug_code) { |
| 1983 Register scratch = scratch0(); |
| 1984 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 1985 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 1986 |
| 1987 __ and_(scratch, scratch, |
| 1988 Operand(kStringRepresentationMask | kStringEncodingMask)); |
| 1989 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 1990 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 1991 __ cmp(scratch, Operand(encoding == String::ONE_BYTE_ENCODING |
| 1992 ? one_byte_seq_type : two_byte_seq_type)); |
| 1993 __ Check(eq, kUnexpectedStringType); |
| 1994 } |
| 1995 |
| 1996 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 1997 if (encoding == String::ONE_BYTE_ENCODING) { |
| 1998 __ ldrb(result, operand); |
| 1999 } else { |
| 2000 __ ldrh(result, operand); |
| 2001 } |
| 2002 } |
| 2003 |
| 2004 |
| 1951 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { | 2005 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { |
| 1952 String::Encoding encoding = instr->hydrogen()->encoding(); | 2006 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 1953 Register string = ToRegister(instr->string()); | 2007 Register string = ToRegister(instr->string()); |
| 1954 Register value = ToRegister(instr->value()); | 2008 Register value = ToRegister(instr->value()); |
| 1955 | 2009 |
| 1956 if (FLAG_debug_code) { | 2010 if (FLAG_debug_code) { |
| 1957 Register scratch = scratch0(); | 2011 Register scratch = scratch0(); |
| 1958 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); | 2012 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 1959 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 2013 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 1960 | 2014 |
| (...skipping 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3019 | 3073 |
| 3020 | 3074 |
| 3021 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3075 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 3022 HObjectAccess access = instr->hydrogen()->access(); | 3076 HObjectAccess access = instr->hydrogen()->access(); |
| 3023 int offset = access.offset(); | 3077 int offset = access.offset(); |
| 3024 Register object = ToRegister(instr->object()); | 3078 Register object = ToRegister(instr->object()); |
| 3025 | 3079 |
| 3026 if (access.IsExternalMemory()) { | 3080 if (access.IsExternalMemory()) { |
| 3027 Register result = ToRegister(instr->result()); | 3081 Register result = ToRegister(instr->result()); |
| 3028 MemOperand operand = MemOperand(object, offset); | 3082 MemOperand operand = MemOperand(object, offset); |
| 3029 if (access.representation().IsByte()) { | 3083 __ Load(result, operand, access.representation()); |
| 3030 __ ldrb(result, operand); | |
| 3031 } else { | |
| 3032 __ ldr(result, operand); | |
| 3033 } | |
| 3034 return; | 3084 return; |
| 3035 } | 3085 } |
| 3036 | 3086 |
| 3037 if (instr->hydrogen()->representation().IsDouble()) { | 3087 if (instr->hydrogen()->representation().IsDouble()) { |
| 3038 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3088 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 3039 __ vldr(result, FieldMemOperand(object, offset)); | 3089 __ vldr(result, FieldMemOperand(object, offset)); |
| 3040 return; | 3090 return; |
| 3041 } | 3091 } |
| 3042 | 3092 |
| 3043 Register result = ToRegister(instr->result()); | 3093 Register result = ToRegister(instr->result()); |
| 3044 if (!access.IsInobject()) { | 3094 if (!access.IsInobject()) { |
| 3045 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3095 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 3046 object = result; | 3096 object = result; |
| 3047 } | 3097 } |
| 3048 MemOperand operand = FieldMemOperand(object, offset); | 3098 MemOperand operand = FieldMemOperand(object, offset); |
| 3049 if (access.representation().IsByte()) { | 3099 __ Load(result, operand, access.representation()); |
| 3050 __ ldrb(result, operand); | |
| 3051 } else { | |
| 3052 __ ldr(result, operand); | |
| 3053 } | |
| 3054 } | 3100 } |
| 3055 | 3101 |
| 3056 | 3102 |
| 3057 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3103 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 3058 ASSERT(ToRegister(instr->context()).is(cp)); | 3104 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3059 ASSERT(ToRegister(instr->object()).is(r0)); | 3105 ASSERT(ToRegister(instr->object()).is(r0)); |
| 3060 ASSERT(ToRegister(instr->result()).is(r0)); | 3106 ASSERT(ToRegister(instr->result()).is(r0)); |
| 3061 | 3107 |
| 3062 // Name is always in r2. | 3108 // Name is always in r2. |
| 3063 __ mov(r2, Operand(instr->name())); | 3109 __ mov(r2, Operand(instr->name())); |
| (...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4146 Representation representation = instr->representation(); | 4192 Representation representation = instr->representation(); |
| 4147 | 4193 |
| 4148 Register object = ToRegister(instr->object()); | 4194 Register object = ToRegister(instr->object()); |
| 4149 Register scratch = scratch0(); | 4195 Register scratch = scratch0(); |
| 4150 HObjectAccess access = instr->hydrogen()->access(); | 4196 HObjectAccess access = instr->hydrogen()->access(); |
| 4151 int offset = access.offset(); | 4197 int offset = access.offset(); |
| 4152 | 4198 |
| 4153 if (access.IsExternalMemory()) { | 4199 if (access.IsExternalMemory()) { |
| 4154 Register value = ToRegister(instr->value()); | 4200 Register value = ToRegister(instr->value()); |
| 4155 MemOperand operand = MemOperand(object, offset); | 4201 MemOperand operand = MemOperand(object, offset); |
| 4156 if (representation.IsByte()) { | 4202 __ Store(value, operand, representation); |
| 4157 __ strb(value, operand); | |
| 4158 } else { | |
| 4159 __ str(value, operand); | |
| 4160 } | |
| 4161 return; | 4203 return; |
| 4162 } | 4204 } |
| 4163 | 4205 |
| 4164 Handle<Map> transition = instr->transition(); | 4206 Handle<Map> transition = instr->transition(); |
| 4165 | 4207 |
| 4166 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4208 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4167 Register value = ToRegister(instr->value()); | 4209 Register value = ToRegister(instr->value()); |
| 4168 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4210 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4169 __ SmiTst(value); | 4211 __ SmiTst(value); |
| 4170 DeoptimizeIf(eq, instr->environment()); | 4212 DeoptimizeIf(eq, instr->environment()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 4196 } | 4238 } |
| 4197 | 4239 |
| 4198 // Do the store. | 4240 // Do the store. |
| 4199 Register value = ToRegister(instr->value()); | 4241 Register value = ToRegister(instr->value()); |
| 4200 ASSERT(!object.is(value)); | 4242 ASSERT(!object.is(value)); |
| 4201 SmiCheck check_needed = | 4243 SmiCheck check_needed = |
| 4202 instr->hydrogen()->value()->IsHeapObject() | 4244 instr->hydrogen()->value()->IsHeapObject() |
| 4203 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4245 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4204 if (access.IsInobject()) { | 4246 if (access.IsInobject()) { |
| 4205 MemOperand operand = FieldMemOperand(object, offset); | 4247 MemOperand operand = FieldMemOperand(object, offset); |
| 4206 if (representation.IsByte()) { | 4248 __ Store(value, operand, representation); |
| 4207 __ strb(value, operand); | |
| 4208 } else { | |
| 4209 __ str(value, operand); | |
| 4210 } | |
| 4211 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4249 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4212 // Update the write barrier for the object for in-object properties. | 4250 // Update the write barrier for the object for in-object properties. |
| 4213 __ RecordWriteField(object, | 4251 __ RecordWriteField(object, |
| 4214 offset, | 4252 offset, |
| 4215 value, | 4253 value, |
| 4216 scratch, | 4254 scratch, |
| 4217 GetLinkRegisterState(), | 4255 GetLinkRegisterState(), |
| 4218 kSaveFPRegs, | 4256 kSaveFPRegs, |
| 4219 EMIT_REMEMBERED_SET, | 4257 EMIT_REMEMBERED_SET, |
| 4220 check_needed); | 4258 check_needed); |
| 4221 } | 4259 } |
| 4222 } else { | 4260 } else { |
| 4223 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 4261 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 4224 MemOperand operand = FieldMemOperand(scratch, offset); | 4262 MemOperand operand = FieldMemOperand(scratch, offset); |
| 4225 if (representation.IsByte()) { | 4263 __ Store(value, operand, representation); |
| 4226 __ strb(value, operand); | |
| 4227 } else { | |
| 4228 __ str(value, operand); | |
| 4229 } | |
| 4230 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4264 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4231 // Update the write barrier for the properties array. | 4265 // Update the write barrier for the properties array. |
| 4232 // object is used as a scratch register. | 4266 // object is used as a scratch register. |
| 4233 __ RecordWriteField(scratch, | 4267 __ RecordWriteField(scratch, |
| 4234 offset, | 4268 offset, |
| 4235 value, | 4269 value, |
| 4236 object, | 4270 object, |
| 4237 GetLinkRegisterState(), | 4271 GetLinkRegisterState(), |
| 4238 kSaveFPRegs, | 4272 kSaveFPRegs, |
| 4239 EMIT_REMEMBERED_SET, | 4273 EMIT_REMEMBERED_SET, |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4521 Register temp = ToRegister(instr->temp()); | 4555 Register temp = ToRegister(instr->temp()); |
| 4522 Label no_memento_found; | 4556 Label no_memento_found; |
| 4523 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4557 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4524 DeoptimizeIf(eq, instr->environment()); | 4558 DeoptimizeIf(eq, instr->environment()); |
| 4525 __ bind(&no_memento_found); | 4559 __ bind(&no_memento_found); |
| 4526 } | 4560 } |
| 4527 | 4561 |
| 4528 | 4562 |
| 4529 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4563 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4530 ASSERT(ToRegister(instr->context()).is(cp)); | 4564 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4531 __ push(ToRegister(instr->left())); | 4565 if (FLAG_new_string_add) { |
| 4532 __ push(ToRegister(instr->right())); | 4566 ASSERT(ToRegister(instr->left()).is(r1)); |
| 4533 StringAddStub stub(instr->hydrogen()->flags()); | 4567 ASSERT(ToRegister(instr->right()).is(r0)); |
| 4534 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4568 NewStringAddStub stub(instr->hydrogen()->flags(), |
| 4569 isolate()->heap()->GetPretenureMode()); |
| 4570 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4571 } else { |
| 4572 __ push(ToRegister(instr->left())); |
| 4573 __ push(ToRegister(instr->right())); |
| 4574 StringAddStub stub(instr->hydrogen()->flags()); |
| 4575 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4576 } |
| 4535 } | 4577 } |
| 4536 | 4578 |
| 4537 | 4579 |
| 4538 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4580 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4539 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4581 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4540 public: | 4582 public: |
| 4541 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4583 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4542 : LDeferredCode(codegen), instr_(instr) { } | 4584 : LDeferredCode(codegen), instr_(instr) { } |
| 4543 virtual void Generate() V8_OVERRIDE { | 4585 virtual void Generate() V8_OVERRIDE { |
| 4544 codegen()->DoDeferredStringCharCodeAt(instr_); | 4586 codegen()->DoDeferredStringCharCodeAt(instr_); |
| (...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5653 // the special case below. | 5695 // the special case below. |
| 5654 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5696 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5655 type = Deoptimizer::LAZY; | 5697 type = Deoptimizer::LAZY; |
| 5656 } | 5698 } |
| 5657 | 5699 |
| 5658 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 5700 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5659 DeoptimizeIf(al, instr->environment(), type); | 5701 DeoptimizeIf(al, instr->environment(), type); |
| 5660 } | 5702 } |
| 5661 | 5703 |
| 5662 | 5704 |
| 5705 void LCodeGen::DoDummy(LDummy* instr) { |
| 5706 // Nothing to see here, move on! |
| 5707 } |
| 5708 |
| 5709 |
| 5663 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5710 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5664 // Nothing to see here, move on! | 5711 // Nothing to see here, move on! |
| 5665 } | 5712 } |
| 5666 | 5713 |
| 5667 | 5714 |
| 5668 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5715 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 5669 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5716 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 5670 LoadContextFromDeferred(instr->context()); | 5717 LoadContextFromDeferred(instr->context()); |
| 5671 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5718 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 5672 RecordSafepointWithLazyDeopt( | 5719 RecordSafepointWithLazyDeopt( |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5836 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5883 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5837 __ ldr(result, FieldMemOperand(scratch, | 5884 __ ldr(result, FieldMemOperand(scratch, |
| 5838 FixedArray::kHeaderSize - kPointerSize)); | 5885 FixedArray::kHeaderSize - kPointerSize)); |
| 5839 __ bind(&done); | 5886 __ bind(&done); |
| 5840 } | 5887 } |
| 5841 | 5888 |
| 5842 | 5889 |
| 5843 #undef __ | 5890 #undef __ |
| 5844 | 5891 |
| 5845 } } // namespace v8::internal | 5892 } } // namespace v8::internal |
| OLD | NEW |