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 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 // Subtract from 0 if source was negative. | 473 // Subtract from 0 if source was negative. |
474 __ rsb(source_, source_, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 474 __ rsb(source_, source_, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
475 | 475 |
476 // We have -1, 0 or 1, which we treat specially. Register source_ contains | 476 // We have -1, 0 or 1, which we treat specially. Register source_ contains |
477 // absolute value: it is either equal to 1 (special case of -1 and 1), | 477 // absolute value: it is either equal to 1 (special case of -1 and 1), |
478 // greater than 1 (not a special case) or less than 1 (special case of 0). | 478 // greater than 1 (not a special case) or less than 1 (special case of 0). |
479 __ cmp(source_, Operand(1)); | 479 __ cmp(source_, Operand(1)); |
480 __ b(gt, ¬_special); | 480 __ b(gt, ¬_special); |
481 | 481 |
482 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). | 482 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). |
483 static const uint32_t exponent_word_for_1 = | 483 const uint32_t exponent_word_for_1 = |
484 HeapNumber::kExponentBias << HeapNumber::kExponentShift; | 484 HeapNumber::kExponentBias << HeapNumber::kExponentShift; |
485 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq); | 485 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq); |
486 // 1, 0 and -1 all have 0 for the second word. | 486 // 1, 0 and -1 all have 0 for the second word. |
487 __ mov(mantissa, Operand(0, RelocInfo::NONE)); | 487 __ mov(mantissa, Operand(0, RelocInfo::NONE)); |
488 __ Ret(); | 488 __ Ret(); |
489 | 489 |
490 __ bind(¬_special); | 490 __ bind(¬_special); |
491 // Count leading zeros. Uses mantissa for a scratch register on pre-ARM5. | 491 // Count leading zeros. Uses mantissa for a scratch register on pre-ARM5. |
492 // Gets the wrong answer for 0, but we already checked for that case above. | 492 // Gets the wrong answer for 0, but we already checked for that case above. |
493 __ CountLeadingZeros(zeros_, source_, mantissa); | 493 __ CountLeadingZeros(zeros_, source_, mantissa); |
(...skipping 3736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4230 | 4230 |
4231 Register InstanceofStub::left() { return r0; } | 4231 Register InstanceofStub::left() { return r0; } |
4232 | 4232 |
4233 | 4233 |
4234 Register InstanceofStub::right() { return r1; } | 4234 Register InstanceofStub::right() { return r1; } |
4235 | 4235 |
4236 | 4236 |
4237 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 4237 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
4238 // The displacement is the offset of the last parameter (if any) | 4238 // The displacement is the offset of the last parameter (if any) |
4239 // relative to the frame pointer. | 4239 // relative to the frame pointer. |
4240 static const int kDisplacement = | 4240 const int kDisplacement = |
4241 StandardFrameConstants::kCallerSPOffset - kPointerSize; | 4241 StandardFrameConstants::kCallerSPOffset - kPointerSize; |
4242 | 4242 |
4243 // Check that the key is a smi. | 4243 // Check that the key is a smi. |
4244 Label slow; | 4244 Label slow; |
4245 __ JumpIfNotSmi(r1, &slow); | 4245 __ JumpIfNotSmi(r1, &slow); |
4246 | 4246 |
4247 // Check if the calling frame is an arguments adaptor frame. | 4247 // Check if the calling frame is an arguments adaptor frame. |
4248 Label adaptor; | 4248 Label adaptor; |
4249 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 4249 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
4250 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 4250 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4615 #ifdef V8_INTERPRETED_REGEXP | 4615 #ifdef V8_INTERPRETED_REGEXP |
4616 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 4616 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
4617 #else // V8_INTERPRETED_REGEXP | 4617 #else // V8_INTERPRETED_REGEXP |
4618 | 4618 |
4619 // Stack frame on entry. | 4619 // Stack frame on entry. |
4620 // sp[0]: last_match_info (expected JSArray) | 4620 // sp[0]: last_match_info (expected JSArray) |
4621 // sp[4]: previous index | 4621 // sp[4]: previous index |
4622 // sp[8]: subject string | 4622 // sp[8]: subject string |
4623 // sp[12]: JSRegExp object | 4623 // sp[12]: JSRegExp object |
4624 | 4624 |
4625 static const int kLastMatchInfoOffset = 0 * kPointerSize; | 4625 const int kLastMatchInfoOffset = 0 * kPointerSize; |
4626 static const int kPreviousIndexOffset = 1 * kPointerSize; | 4626 const int kPreviousIndexOffset = 1 * kPointerSize; |
4627 static const int kSubjectOffset = 2 * kPointerSize; | 4627 const int kSubjectOffset = 2 * kPointerSize; |
4628 static const int kJSRegExpOffset = 3 * kPointerSize; | 4628 const int kJSRegExpOffset = 3 * kPointerSize; |
4629 | 4629 |
4630 Label runtime, invoke_regexp; | 4630 Label runtime, invoke_regexp; |
4631 | 4631 |
4632 // Allocation of registers for this function. These are in callee save | 4632 // Allocation of registers for this function. These are in callee save |
4633 // registers and will be preserved by the call to the native RegExp code, as | 4633 // registers and will be preserved by the call to the native RegExp code, as |
4634 // this code is called using the normal C calling convention. When calling | 4634 // this code is called using the normal C calling convention. When calling |
4635 // directly from generated code the native RegExp code will not do a GC and | 4635 // directly from generated code the native RegExp code will not do a GC and |
4636 // therefore the content of these registers are safe to use after the call. | 4636 // therefore the content of these registers are safe to use after the call. |
4637 Register subject = r4; | 4637 Register subject = r4; |
4638 Register regexp_data = r5; | 4638 Register regexp_data = r5; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4817 | 4817 |
4818 // r1: previous index | 4818 // r1: previous index |
4819 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); | 4819 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); |
4820 // r7: code | 4820 // r7: code |
4821 // subject: Subject string | 4821 // subject: Subject string |
4822 // regexp_data: RegExp data (FixedArray) | 4822 // regexp_data: RegExp data (FixedArray) |
4823 // All checks done. Now push arguments for native regexp code. | 4823 // All checks done. Now push arguments for native regexp code. |
4824 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); | 4824 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); |
4825 | 4825 |
4826 // Isolates: note we add an additional parameter here (isolate pointer). | 4826 // Isolates: note we add an additional parameter here (isolate pointer). |
4827 static const int kRegExpExecuteArguments = 8; | 4827 const int kRegExpExecuteArguments = 8; |
4828 static const int kParameterRegisters = 4; | 4828 const int kParameterRegisters = 4; |
4829 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); | 4829 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
4830 | 4830 |
4831 // Stack pointer now points to cell where return address is to be written. | 4831 // Stack pointer now points to cell where return address is to be written. |
4832 // Arguments are before that on the stack or in registers. | 4832 // Arguments are before that on the stack or in registers. |
4833 | 4833 |
4834 // Argument 8 (sp[16]): Pass current isolate address. | 4834 // Argument 8 (sp[16]): Pass current isolate address. |
4835 __ mov(r0, Operand(ExternalReference::isolate_address())); | 4835 __ mov(r0, Operand(ExternalReference::isolate_address())); |
4836 __ str(r0, MemOperand(sp, 4 * kPointerSize)); | 4836 __ str(r0, MemOperand(sp, 4 * kPointerSize)); |
4837 | 4837 |
4838 // Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript. | 4838 // Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript. |
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5707 // Registers | 5707 // Registers |
5708 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5708 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
5709 // hash: hash of two character string | 5709 // hash: hash of two character string |
5710 // mask: capacity mask | 5710 // mask: capacity mask |
5711 // first_symbol_table_element: address of the first element of | 5711 // first_symbol_table_element: address of the first element of |
5712 // the symbol table | 5712 // the symbol table |
5713 // undefined: the undefined object | 5713 // undefined: the undefined object |
5714 // scratch: - | 5714 // scratch: - |
5715 | 5715 |
5716 // Perform a number of probes in the symbol table. | 5716 // Perform a number of probes in the symbol table. |
5717 static const int kProbes = 4; | 5717 const int kProbes = 4; |
5718 Label found_in_symbol_table; | 5718 Label found_in_symbol_table; |
5719 Label next_probe[kProbes]; | 5719 Label next_probe[kProbes]; |
5720 Register candidate = scratch5; // Scratch register contains candidate. | 5720 Register candidate = scratch5; // Scratch register contains candidate. |
5721 for (int i = 0; i < kProbes; i++) { | 5721 for (int i = 0; i < kProbes; i++) { |
5722 // Calculate entry in symbol table. | 5722 // Calculate entry in symbol table. |
5723 if (i > 0) { | 5723 if (i > 0) { |
5724 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); | 5724 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); |
5725 } else { | 5725 } else { |
5726 __ mov(candidate, hash); | 5726 __ mov(candidate, hash); |
5727 } | 5727 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5832 // sp[4]: from | 5832 // sp[4]: from |
5833 // sp[8]: string | 5833 // sp[8]: string |
5834 | 5834 |
5835 // This stub is called from the native-call %_SubString(...), so | 5835 // This stub is called from the native-call %_SubString(...), so |
5836 // nothing can be assumed about the arguments. It is tested that: | 5836 // nothing can be assumed about the arguments. It is tested that: |
5837 // "string" is a sequential string, | 5837 // "string" is a sequential string, |
5838 // both "from" and "to" are smis, and | 5838 // both "from" and "to" are smis, and |
5839 // 0 <= from <= to <= string.length. | 5839 // 0 <= from <= to <= string.length. |
5840 // If any of these assumptions fail, we call the runtime system. | 5840 // If any of these assumptions fail, we call the runtime system. |
5841 | 5841 |
5842 static const int kToOffset = 0 * kPointerSize; | 5842 const int kToOffset = 0 * kPointerSize; |
5843 static const int kFromOffset = 1 * kPointerSize; | 5843 const int kFromOffset = 1 * kPointerSize; |
5844 static const int kStringOffset = 2 * kPointerSize; | 5844 const int kStringOffset = 2 * kPointerSize; |
5845 | 5845 |
5846 __ Ldrd(r2, r3, MemOperand(sp, kToOffset)); | 5846 __ Ldrd(r2, r3, MemOperand(sp, kToOffset)); |
5847 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 5847 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
5848 STATIC_ASSERT(kSmiTag == 0); | 5848 STATIC_ASSERT(kSmiTag == 0); |
5849 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5849 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
5850 | 5850 |
5851 // I.e., arithmetic shift right by one un-smi-tags. | 5851 // I.e., arithmetic shift right by one un-smi-tags. |
5852 __ mov(r2, Operand(r2, ASR, 1), SetCC); | 5852 __ mov(r2, Operand(r2, ASR, 1), SetCC); |
5853 __ mov(r3, Operand(r3, ASR, 1), SetCC, cc); | 5853 __ mov(r3, Operand(r3, ASR, 1), SetCC, cc); |
5854 // If either to or from had the smi tag bit set, then carry is set now. | 5854 // If either to or from had the smi tag bit set, then carry is set now. |
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7051 __ mov(result, Operand::Zero()); | 7051 __ mov(result, Operand::Zero()); |
7052 __ Ret(); | 7052 __ Ret(); |
7053 } | 7053 } |
7054 | 7054 |
7055 | 7055 |
7056 struct AheadOfTimeWriteBarrierStubList { | 7056 struct AheadOfTimeWriteBarrierStubList { |
7057 Register object, value, address; | 7057 Register object, value, address; |
7058 RememberedSetAction action; | 7058 RememberedSetAction action; |
7059 }; | 7059 }; |
7060 | 7060 |
| 7061 #define REG(Name) { kRegister_ ## Name ## _Code } |
7061 | 7062 |
7062 struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 7063 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
7063 // Used in RegExpExecStub. | 7064 // Used in RegExpExecStub. |
7064 { r6, r4, r7, EMIT_REMEMBERED_SET }, | 7065 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, |
7065 { r6, r2, r7, EMIT_REMEMBERED_SET }, | 7066 { REG(r6), REG(r2), REG(r7), EMIT_REMEMBERED_SET }, |
7066 // Used in CompileArrayPushCall. | 7067 // Used in CompileArrayPushCall. |
7067 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. | 7068 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. |
7068 // Also used in KeyedStoreIC::GenerateGeneric. | 7069 // Also used in KeyedStoreIC::GenerateGeneric. |
7069 { r3, r4, r5, EMIT_REMEMBERED_SET }, | 7070 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, |
7070 // Used in CompileStoreGlobal. | 7071 // Used in CompileStoreGlobal. |
7071 { r4, r1, r2, OMIT_REMEMBERED_SET }, | 7072 { REG(r4), REG(r1), REG(r2), OMIT_REMEMBERED_SET }, |
7072 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. | 7073 // Used in StoreStubCompiler::CompileStoreField via GenerateStoreField. |
7073 { r1, r2, r3, EMIT_REMEMBERED_SET }, | 7074 { REG(r1), REG(r2), REG(r3), EMIT_REMEMBERED_SET }, |
7074 { r3, r2, r1, EMIT_REMEMBERED_SET }, | 7075 { REG(r3), REG(r2), REG(r1), EMIT_REMEMBERED_SET }, |
7075 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. | 7076 // Used in KeyedStoreStubCompiler::CompileStoreField via GenerateStoreField. |
7076 { r2, r1, r3, EMIT_REMEMBERED_SET }, | 7077 { REG(r2), REG(r1), REG(r3), EMIT_REMEMBERED_SET }, |
7077 { r3, r1, r2, EMIT_REMEMBERED_SET }, | 7078 { REG(r3), REG(r1), REG(r2), EMIT_REMEMBERED_SET }, |
7078 // KeyedStoreStubCompiler::GenerateStoreFastElement. | 7079 // KeyedStoreStubCompiler::GenerateStoreFastElement. |
7079 { r3, r2, r4, EMIT_REMEMBERED_SET }, | 7080 { REG(r3), REG(r2), REG(r4), EMIT_REMEMBERED_SET }, |
7080 { r2, r3, r4, EMIT_REMEMBERED_SET }, | 7081 { REG(r2), REG(r3), REG(r4), EMIT_REMEMBERED_SET }, |
7081 // ElementsTransitionGenerator::GenerateSmiOnlyToObject | 7082 // ElementsTransitionGenerator::GenerateSmiOnlyToObject |
7082 // and ElementsTransitionGenerator::GenerateSmiOnlyToDouble | 7083 // and ElementsTransitionGenerator::GenerateSmiOnlyToDouble |
7083 // and ElementsTransitionGenerator::GenerateDoubleToObject | 7084 // and ElementsTransitionGenerator::GenerateDoubleToObject |
7084 { r2, r3, r9, EMIT_REMEMBERED_SET }, | 7085 { REG(r2), REG(r3), REG(r9), EMIT_REMEMBERED_SET }, |
7085 { r2, r3, r9, OMIT_REMEMBERED_SET }, | 7086 { REG(r2), REG(r3), REG(r9), OMIT_REMEMBERED_SET }, |
7086 // ElementsTransitionGenerator::GenerateDoubleToObject | 7087 // ElementsTransitionGenerator::GenerateDoubleToObject |
7087 { r6, r2, r0, EMIT_REMEMBERED_SET }, | 7088 { REG(r6), REG(r2), REG(r0), EMIT_REMEMBERED_SET }, |
7088 { r2, r6, r9, EMIT_REMEMBERED_SET }, | 7089 { REG(r2), REG(r6), REG(r9), EMIT_REMEMBERED_SET }, |
7089 // StoreArrayLiteralElementStub::Generate | 7090 // StoreArrayLiteralElementStub::Generate |
7090 { r5, r0, r6, EMIT_REMEMBERED_SET }, | 7091 { REG(r5), REG(r0), REG(r6), EMIT_REMEMBERED_SET }, |
7091 // Null termination. | 7092 // Null termination. |
7092 { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} | 7093 { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET} |
7093 }; | 7094 }; |
7094 | 7095 |
| 7096 #undef REG |
7095 | 7097 |
7096 bool RecordWriteStub::IsPregenerated() { | 7098 bool RecordWriteStub::IsPregenerated() { |
7097 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 7099 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
7098 !entry->object.is(no_reg); | 7100 !entry->object.is(no_reg); |
7099 entry++) { | 7101 entry++) { |
7100 if (object_.is(entry->object) && | 7102 if (object_.is(entry->object) && |
7101 value_.is(entry->value) && | 7103 value_.is(entry->value) && |
7102 address_.is(entry->address) && | 7104 address_.is(entry->address) && |
7103 remembered_set_action_ == entry->action && | 7105 remembered_set_action_ == entry->action && |
7104 save_fp_regs_mode_ == kDontSaveFPRegs) { | 7106 save_fp_regs_mode_ == kDontSaveFPRegs) { |
7105 return true; | 7107 return true; |
7106 } | 7108 } |
7107 } | 7109 } |
7108 return false; | 7110 return false; |
7109 } | 7111 } |
7110 | 7112 |
7111 | 7113 |
7112 bool StoreBufferOverflowStub::IsPregenerated() { | 7114 bool StoreBufferOverflowStub::IsPregenerated() { |
7113 return save_doubles_ == kDontSaveFPRegs || ISOLATE->fp_stubs_generated(); | 7115 return save_doubles_ == kDontSaveFPRegs || ISOLATE->fp_stubs_generated(); |
7114 } | 7116 } |
7115 | 7117 |
7116 | 7118 |
7117 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() { | 7119 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() { |
7118 StoreBufferOverflowStub stub1(kDontSaveFPRegs); | 7120 StoreBufferOverflowStub stub1(kDontSaveFPRegs); |
7119 stub1.GetCode()->set_is_pregenerated(true); | 7121 stub1.GetCode()->set_is_pregenerated(true); |
7120 } | 7122 } |
7121 | 7123 |
7122 | 7124 |
7123 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() { | 7125 void RecordWriteStub::GenerateFixedRegStubsAheadOfTime() { |
7124 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 7126 for (const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
7125 !entry->object.is(no_reg); | 7127 !entry->object.is(no_reg); |
7126 entry++) { | 7128 entry++) { |
7127 RecordWriteStub stub(entry->object, | 7129 RecordWriteStub stub(entry->object, |
7128 entry->value, | 7130 entry->value, |
7129 entry->address, | 7131 entry->address, |
7130 entry->action, | 7132 entry->action, |
7131 kDontSaveFPRegs); | 7133 kDontSaveFPRegs); |
7132 stub.GetCode()->set_is_pregenerated(true); | 7134 stub.GetCode()->set_is_pregenerated(true); |
7133 } | 7135 } |
7134 } | 7136 } |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7380 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r2, | 7382 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r2, |
7381 &slow_elements); | 7383 &slow_elements); |
7382 __ Ret(); | 7384 __ Ret(); |
7383 } | 7385 } |
7384 | 7386 |
7385 #undef __ | 7387 #undef __ |
7386 | 7388 |
7387 } } // namespace v8::internal | 7389 } } // namespace v8::internal |
7388 | 7390 |
7389 #endif // V8_TARGET_ARCH_ARM | 7391 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |