OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 20 matching lines...) Expand all Loading... |
32 | 32 |
33 | 33 |
34 namespace v8 { | 34 namespace v8 { |
35 namespace internal { | 35 namespace internal { |
36 | 36 |
37 | 37 |
38 // Compute a transcendental math function natively, or call the | 38 // Compute a transcendental math function natively, or call the |
39 // TranscendentalCache runtime function. | 39 // TranscendentalCache runtime function. |
40 class TranscendentalCacheStub: public CodeStub { | 40 class TranscendentalCacheStub: public CodeStub { |
41 public: | 41 public: |
42 explicit TranscendentalCacheStub(TranscendentalCache::Type type) | 42 enum ArgumentType { |
43 : type_(type) {} | 43 TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits, |
| 44 UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits |
| 45 }; |
| 46 |
| 47 TranscendentalCacheStub(TranscendentalCache::Type type, |
| 48 ArgumentType argument_type) |
| 49 : type_(type), argument_type_(argument_type) { } |
44 void Generate(MacroAssembler* masm); | 50 void Generate(MacroAssembler* masm); |
45 private: | 51 private: |
46 TranscendentalCache::Type type_; | 52 TranscendentalCache::Type type_; |
| 53 ArgumentType argument_type_; |
| 54 void GenerateCallCFunction(MacroAssembler* masm, Register scratch); |
| 55 |
47 Major MajorKey() { return TranscendentalCache; } | 56 Major MajorKey() { return TranscendentalCache; } |
48 int MinorKey() { return type_; } | 57 int MinorKey() { return type_ | argument_type_; } |
49 Runtime::FunctionId RuntimeFunction(); | 58 Runtime::FunctionId RuntimeFunction(); |
50 }; | 59 }; |
51 | 60 |
52 | 61 |
53 class ToBooleanStub: public CodeStub { | 62 class ToBooleanStub: public CodeStub { |
54 public: | 63 public: |
55 explicit ToBooleanStub(Register tos) : tos_(tos) { } | 64 explicit ToBooleanStub(Register tos) : tos_(tos) { } |
56 | 65 |
57 void Generate(MacroAssembler* masm); | 66 void Generate(MacroAssembler* masm); |
58 | 67 |
59 private: | 68 private: |
60 Register tos_; | 69 Register tos_; |
61 Major MajorKey() { return ToBoolean; } | 70 Major MajorKey() { return ToBoolean; } |
62 int MinorKey() { return tos_.code(); } | 71 int MinorKey() { return tos_.code(); } |
63 }; | 72 }; |
64 | 73 |
65 | 74 |
66 class GenericBinaryOpStub : public CodeStub { | 75 class TypeRecordingUnaryOpStub: public CodeStub { |
67 public: | 76 public: |
68 static const int kUnknownIntValue = -1; | 77 TypeRecordingUnaryOpStub(Token::Value op, UnaryOverwriteMode mode) |
69 | |
70 GenericBinaryOpStub(Token::Value op, | |
71 OverwriteMode mode, | |
72 Register lhs, | |
73 Register rhs, | |
74 int constant_rhs = kUnknownIntValue) | |
75 : op_(op), | 78 : op_(op), |
76 mode_(mode), | 79 mode_(mode), |
77 lhs_(lhs), | 80 operand_type_(TRUnaryOpIC::UNINITIALIZED), |
78 rhs_(rhs), | 81 name_(NULL) { |
79 constant_rhs_(constant_rhs), | 82 } |
80 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)), | |
81 runtime_operands_type_(BinaryOpIC::UNINIT_OR_SMI), | |
82 name_(NULL) { } | |
83 | 83 |
84 GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) | 84 TypeRecordingUnaryOpStub( |
| 85 int key, |
| 86 TRUnaryOpIC::TypeInfo operand_type) |
85 : op_(OpBits::decode(key)), | 87 : op_(OpBits::decode(key)), |
86 mode_(ModeBits::decode(key)), | 88 mode_(ModeBits::decode(key)), |
87 lhs_(LhsRegister(RegisterBits::decode(key))), | 89 operand_type_(operand_type), |
88 rhs_(RhsRegister(RegisterBits::decode(key))), | 90 name_(NULL) { |
89 constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))), | 91 } |
90 specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)), | |
91 runtime_operands_type_(type_info), | |
92 name_(NULL) { } | |
93 | 92 |
94 private: | 93 private: |
95 Token::Value op_; | 94 Token::Value op_; |
96 OverwriteMode mode_; | 95 UnaryOverwriteMode mode_; |
97 Register lhs_; | 96 |
98 Register rhs_; | 97 // Operand type information determined at runtime. |
99 int constant_rhs_; | 98 TRUnaryOpIC::TypeInfo operand_type_; |
100 bool specialized_on_rhs_; | 99 |
101 BinaryOpIC::TypeInfo runtime_operands_type_; | |
102 char* name_; | 100 char* name_; |
103 | 101 |
104 static const int kMaxKnownRhs = 0x40000000; | |
105 static const int kKnownRhsKeyBits = 6; | |
106 | |
107 // Minor key encoding in 16 bits. | |
108 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; | |
109 class OpBits: public BitField<Token::Value, 2, 6> {}; | |
110 class TypeInfoBits: public BitField<int, 8, 3> {}; | |
111 class RegisterBits: public BitField<bool, 11, 1> {}; | |
112 class KnownIntBits: public BitField<int, 12, kKnownRhsKeyBits> {}; | |
113 | |
114 Major MajorKey() { return GenericBinaryOp; } | |
115 int MinorKey() { | |
116 ASSERT((lhs_.is(a0) && rhs_.is(a1)) || | |
117 (lhs_.is(a1) && rhs_.is(a0))); | |
118 // Encode the parameters in a unique 16 bit value. | |
119 return OpBits::encode(op_) | |
120 | ModeBits::encode(mode_) | |
121 | KnownIntBits::encode(MinorKeyForKnownInt()) | |
122 | TypeInfoBits::encode(runtime_operands_type_) | |
123 | RegisterBits::encode(lhs_.is(a0)); | |
124 } | |
125 | |
126 void Generate(MacroAssembler* masm); | |
127 void HandleNonSmiBitwiseOp(MacroAssembler* masm, | |
128 Register lhs, | |
129 Register rhs); | |
130 void HandleBinaryOpSlowCases(MacroAssembler* masm, | |
131 Label* not_smi, | |
132 Register lhs, | |
133 Register rhs, | |
134 const Builtins::JavaScript& builtin); | |
135 void GenerateTypeTransition(MacroAssembler* masm); | |
136 | |
137 static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) { | |
138 if (constant_rhs == kUnknownIntValue) return false; | |
139 if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3; | |
140 if (op == Token::MOD) { | |
141 if (constant_rhs <= 1) return false; | |
142 if (constant_rhs <= 10) return true; | |
143 if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true; | |
144 return false; | |
145 } | |
146 return false; | |
147 } | |
148 | |
149 int MinorKeyForKnownInt() { | |
150 if (!specialized_on_rhs_) return 0; | |
151 if (constant_rhs_ <= 10) return constant_rhs_ + 1; | |
152 ASSERT(IsPowerOf2(constant_rhs_)); | |
153 int key = 12; | |
154 int d = constant_rhs_; | |
155 while ((d & 1) == 0) { | |
156 key++; | |
157 d >>= 1; | |
158 } | |
159 ASSERT(key >= 0 && key < (1 << kKnownRhsKeyBits)); | |
160 return key; | |
161 } | |
162 | |
163 int KnownBitsForMinorKey(int key) { | |
164 if (!key) return 0; | |
165 if (key <= 11) return key - 1; | |
166 int d = 1; | |
167 while (key != 12) { | |
168 key--; | |
169 d <<= 1; | |
170 } | |
171 return d; | |
172 } | |
173 | |
174 Register LhsRegister(bool lhs_is_a0) { | |
175 return lhs_is_a0 ? a0 : a1; | |
176 } | |
177 | |
178 Register RhsRegister(bool lhs_is_a0) { | |
179 return lhs_is_a0 ? a1 : a0; | |
180 } | |
181 | |
182 bool HasSmiSmiFastPath() { | |
183 return op_ != Token::DIV; | |
184 } | |
185 | |
186 bool ShouldGenerateSmiCode() { | |
187 return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) && | |
188 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS && | |
189 runtime_operands_type_ != BinaryOpIC::STRINGS; | |
190 } | |
191 | |
192 bool ShouldGenerateFPCode() { | |
193 return runtime_operands_type_ != BinaryOpIC::STRINGS; | |
194 } | |
195 | |
196 virtual int GetCodeKind() { return Code::BINARY_OP_IC; } | |
197 | |
198 virtual InlineCacheState GetICState() { | |
199 return BinaryOpIC::ToState(runtime_operands_type_); | |
200 } | |
201 | |
202 const char* GetName(); | 102 const char* GetName(); |
203 | 103 |
204 virtual void FinishCode(Code* code) { | 104 #ifdef DEBUG |
205 code->set_binary_op_type(runtime_operands_type_); | 105 void Print() { |
| 106 PrintF("TypeRecordingUnaryOpStub %d (op %s), " |
| 107 "(mode %d, runtime_type_info %s)\n", |
| 108 MinorKey(), |
| 109 Token::String(op_), |
| 110 static_cast<int>(mode_), |
| 111 TRUnaryOpIC::GetName(operand_type_)); |
| 112 } |
| 113 #endif |
| 114 |
| 115 class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {}; |
| 116 class OpBits: public BitField<Token::Value, 1, 7> {}; |
| 117 class OperandTypeInfoBits: public BitField<TRUnaryOpIC::TypeInfo, 8, 3> {}; |
| 118 |
| 119 Major MajorKey() { return TypeRecordingUnaryOp; } |
| 120 int MinorKey() { |
| 121 return ModeBits::encode(mode_) |
| 122 | OpBits::encode(op_) |
| 123 | OperandTypeInfoBits::encode(operand_type_); |
206 } | 124 } |
207 | 125 |
208 #ifdef DEBUG | 126 // Note: A lot of the helper functions below will vanish when we use virtual |
209 void Print() { | 127 // function instead of switch more often. |
210 if (!specialized_on_rhs_) { | 128 void Generate(MacroAssembler* masm); |
211 PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_)); | 129 |
212 } else { | 130 void GenerateTypeTransition(MacroAssembler* masm); |
213 PrintF("GenericBinaryOpStub (%s by %d)\n", | 131 |
214 Token::String(op_), | 132 void GenerateSmiStub(MacroAssembler* masm); |
215 constant_rhs_); | 133 void GenerateSmiStubSub(MacroAssembler* masm); |
216 } | 134 void GenerateSmiStubBitNot(MacroAssembler* masm); |
| 135 void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow); |
| 136 void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow); |
| 137 |
| 138 void GenerateHeapNumberStub(MacroAssembler* masm); |
| 139 void GenerateHeapNumberStubSub(MacroAssembler* masm); |
| 140 void GenerateHeapNumberStubBitNot(MacroAssembler* masm); |
| 141 void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow); |
| 142 void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow); |
| 143 |
| 144 void GenerateGenericStub(MacroAssembler* masm); |
| 145 void GenerateGenericStubSub(MacroAssembler* masm); |
| 146 void GenerateGenericStubBitNot(MacroAssembler* masm); |
| 147 void GenerateGenericCodeFallback(MacroAssembler* masm); |
| 148 |
| 149 virtual int GetCodeKind() { return Code::TYPE_RECORDING_UNARY_OP_IC; } |
| 150 |
| 151 virtual InlineCacheState GetICState() { |
| 152 return TRUnaryOpIC::ToState(operand_type_); |
217 } | 153 } |
218 #endif | 154 |
| 155 virtual void FinishCode(Code* code) { |
| 156 code->set_type_recording_unary_op_type(operand_type_); |
| 157 } |
219 }; | 158 }; |
220 | 159 |
| 160 |
221 class TypeRecordingBinaryOpStub: public CodeStub { | 161 class TypeRecordingBinaryOpStub: public CodeStub { |
222 public: | 162 public: |
223 TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode) | 163 TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode) |
224 : op_(op), | 164 : op_(op), |
225 mode_(mode), | 165 mode_(mode), |
226 operands_type_(TRBinaryOpIC::UNINITIALIZED), | 166 operands_type_(TRBinaryOpIC::UNINITIALIZED), |
227 result_type_(TRBinaryOpIC::UNINITIALIZED), | 167 result_type_(TRBinaryOpIC::UNINITIALIZED), |
228 name_(NULL) { | 168 name_(NULL) { |
229 UNIMPLEMENTED_MIPS(); | 169 use_fpu_ = CpuFeatures::IsSupported(FPU); |
| 170 ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); |
230 } | 171 } |
231 | 172 |
232 TypeRecordingBinaryOpStub( | 173 TypeRecordingBinaryOpStub( |
233 int key, | 174 int key, |
234 TRBinaryOpIC::TypeInfo operands_type, | 175 TRBinaryOpIC::TypeInfo operands_type, |
235 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED) | 176 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED) |
236 : op_(OpBits::decode(key)), | 177 : op_(OpBits::decode(key)), |
237 mode_(ModeBits::decode(key)), | 178 mode_(ModeBits::decode(key)), |
238 use_fpu_(FPUBits::decode(key)), | 179 use_fpu_(FPUBits::decode(key)), |
239 operands_type_(operands_type), | 180 operands_type_(operands_type), |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 } | 227 } |
287 | 228 |
288 void Generate(MacroAssembler* masm); | 229 void Generate(MacroAssembler* masm); |
289 void GenerateGeneric(MacroAssembler* masm); | 230 void GenerateGeneric(MacroAssembler* masm); |
290 void GenerateSmiSmiOperation(MacroAssembler* masm); | 231 void GenerateSmiSmiOperation(MacroAssembler* masm); |
291 void GenerateFPOperation(MacroAssembler* masm, | 232 void GenerateFPOperation(MacroAssembler* masm, |
292 bool smi_operands, | 233 bool smi_operands, |
293 Label* not_numbers, | 234 Label* not_numbers, |
294 Label* gc_required); | 235 Label* gc_required); |
295 void GenerateSmiCode(MacroAssembler* masm, | 236 void GenerateSmiCode(MacroAssembler* masm, |
| 237 Label* use_runtime, |
296 Label* gc_required, | 238 Label* gc_required, |
297 SmiCodeGenerateHeapNumberResults heapnumber_results); | 239 SmiCodeGenerateHeapNumberResults heapnumber_results); |
298 void GenerateLoadArguments(MacroAssembler* masm); | 240 void GenerateLoadArguments(MacroAssembler* masm); |
299 void GenerateReturn(MacroAssembler* masm); | 241 void GenerateReturn(MacroAssembler* masm); |
300 void GenerateUninitializedStub(MacroAssembler* masm); | 242 void GenerateUninitializedStub(MacroAssembler* masm); |
301 void GenerateSmiStub(MacroAssembler* masm); | 243 void GenerateSmiStub(MacroAssembler* masm); |
302 void GenerateInt32Stub(MacroAssembler* masm); | 244 void GenerateInt32Stub(MacroAssembler* masm); |
303 void GenerateHeapNumberStub(MacroAssembler* masm); | 245 void GenerateHeapNumberStub(MacroAssembler* masm); |
| 246 void GenerateOddballStub(MacroAssembler* masm); |
304 void GenerateStringStub(MacroAssembler* masm); | 247 void GenerateStringStub(MacroAssembler* masm); |
| 248 void GenerateBothStringStub(MacroAssembler* masm); |
305 void GenerateGenericStub(MacroAssembler* masm); | 249 void GenerateGenericStub(MacroAssembler* masm); |
306 void GenerateAddStrings(MacroAssembler* masm); | 250 void GenerateAddStrings(MacroAssembler* masm); |
307 void GenerateCallRuntime(MacroAssembler* masm); | 251 void GenerateCallRuntime(MacroAssembler* masm); |
308 | 252 |
309 void GenerateHeapResultAllocation(MacroAssembler* masm, | 253 void GenerateHeapResultAllocation(MacroAssembler* masm, |
310 Register result, | 254 Register result, |
311 Register heap_number_map, | 255 Register heap_number_map, |
312 Register scratch1, | 256 Register scratch1, |
313 Register scratch2, | 257 Register scratch2, |
314 Label* gc_required); | 258 Label* gc_required); |
(...skipping 12 matching lines...) Expand all Loading... |
327 code->set_type_recording_binary_op_result_type(result_type_); | 271 code->set_type_recording_binary_op_result_type(result_type_); |
328 } | 272 } |
329 | 273 |
330 friend class CodeGenerator; | 274 friend class CodeGenerator; |
331 }; | 275 }; |
332 | 276 |
333 | 277 |
334 // Flag that indicates how to generate code for the stub StringAddStub. | 278 // Flag that indicates how to generate code for the stub StringAddStub. |
335 enum StringAddFlags { | 279 enum StringAddFlags { |
336 NO_STRING_ADD_FLAGS = 0, | 280 NO_STRING_ADD_FLAGS = 0, |
337 NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub. | 281 // Omit left string check in stub (left is definitely a string). |
| 282 NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0, |
| 283 // Omit right string check in stub (right is definitely a string). |
| 284 NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1, |
| 285 // Omit both string checks in stub. |
| 286 NO_STRING_CHECK_IN_STUB = |
| 287 NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB |
338 }; | 288 }; |
339 | 289 |
340 | 290 |
341 class StringAddStub: public CodeStub { | 291 class StringAddStub: public CodeStub { |
342 public: | 292 public: |
343 explicit StringAddStub(StringAddFlags flags) { | 293 explicit StringAddStub(StringAddFlags flags) : flags_(flags) {} |
344 string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0); | |
345 } | |
346 | 294 |
347 private: | 295 private: |
348 Major MajorKey() { return StringAdd; } | 296 Major MajorKey() { return StringAdd; } |
349 int MinorKey() { return string_check_ ? 0 : 1; } | 297 int MinorKey() { return flags_; } |
350 | 298 |
351 void Generate(MacroAssembler* masm); | 299 void Generate(MacroAssembler* masm); |
352 | 300 |
353 // Should the stub check whether arguments are strings? | 301 void GenerateConvertArgument(MacroAssembler* masm, |
354 bool string_check_; | 302 int stack_offset, |
| 303 Register arg, |
| 304 Register scratch1, |
| 305 Register scratch2, |
| 306 Register scratch3, |
| 307 Register scratch4, |
| 308 Label* slow); |
| 309 |
| 310 const StringAddFlags flags_; |
355 }; | 311 }; |
356 | 312 |
357 | 313 |
358 class SubStringStub: public CodeStub { | 314 class SubStringStub: public CodeStub { |
359 public: | 315 public: |
360 SubStringStub() {} | 316 SubStringStub() {} |
361 | 317 |
362 private: | 318 private: |
363 Major MajorKey() { return SubString; } | 319 Major MajorKey() { return SubString; } |
364 int MinorKey() { return 0; } | 320 int MinorKey() { return 0; } |
365 | 321 |
366 void Generate(MacroAssembler* masm); | 322 void Generate(MacroAssembler* masm); |
367 }; | 323 }; |
368 | 324 |
369 | 325 |
370 class StringCompareStub: public CodeStub { | 326 class StringCompareStub: public CodeStub { |
371 public: | 327 public: |
372 StringCompareStub() { } | 328 StringCompareStub() { } |
373 | 329 |
374 // Compare two flat ASCII strings and returns result in v0. | 330 // Compare two flat ASCII strings and returns result in v0. |
375 // Does not use the stack. | |
376 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | 331 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, |
377 Register left, | 332 Register left, |
378 Register right, | 333 Register right, |
379 Register scratch1, | 334 Register scratch1, |
380 Register scratch2, | 335 Register scratch2, |
381 Register scratch3, | 336 Register scratch3, |
382 Register scratch4); | 337 Register scratch4); |
383 | 338 |
| 339 // Compares two flat ASCII strings for equality and returns result |
| 340 // in v0. |
| 341 static void GenerateFlatAsciiStringEquals(MacroAssembler* masm, |
| 342 Register left, |
| 343 Register right, |
| 344 Register scratch1, |
| 345 Register scratch2, |
| 346 Register scratch3); |
| 347 |
384 private: | 348 private: |
385 Major MajorKey() { return StringCompare; } | 349 virtual Major MajorKey() { return StringCompare; } |
386 int MinorKey() { return 0; } | 350 virtual int MinorKey() { return 0; } |
| 351 virtual void Generate(MacroAssembler* masm); |
387 | 352 |
388 void Generate(MacroAssembler* masm); | 353 static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm, |
| 354 Register left, |
| 355 Register right, |
| 356 Register length, |
| 357 Register scratch1, |
| 358 Register scratch2, |
| 359 Register scratch3, |
| 360 Label* chars_not_equal); |
389 }; | 361 }; |
390 | 362 |
391 | 363 |
392 // This stub can convert a signed int32 to a heap number (double). It does | 364 // This stub can convert a signed int32 to a heap number (double). It does |
393 // not work for int32s that are in Smi range! No GC occurs during this stub | 365 // not work for int32s that are in Smi range! No GC occurs during this stub |
394 // so you don't have to set up the frame. | 366 // so you don't have to set up the frame. |
395 class WriteInt32ToHeapNumberStub : public CodeStub { | 367 class WriteInt32ToHeapNumberStub : public CodeStub { |
396 public: | 368 public: |
397 WriteInt32ToHeapNumberStub(Register the_int, | 369 WriteInt32ToHeapNumberStub(Register the_int, |
398 Register the_heap_number, | 370 Register the_heap_number, |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 private: | 450 private: |
479 Major MajorKey() { return RegExpCEntry; } | 451 Major MajorKey() { return RegExpCEntry; } |
480 int MinorKey() { return 0; } | 452 int MinorKey() { return 0; } |
481 | 453 |
482 bool NeedsImmovableCode() { return true; } | 454 bool NeedsImmovableCode() { return true; } |
483 | 455 |
484 const char* GetName() { return "RegExpCEntryStub"; } | 456 const char* GetName() { return "RegExpCEntryStub"; } |
485 }; | 457 }; |
486 | 458 |
487 | 459 |
488 // Generate code the to load an element from a pixel array. The receiver is | 460 class FloatingPointHelper : public AllStatic { |
489 // assumed to not be a smi and to have elements, the caller must guarantee this | 461 public: |
490 // precondition. If the receiver does not have elements that are pixel arrays, | 462 |
491 // the generated code jumps to not_pixel_array. If key is not a smi, then the | 463 enum Destination { |
492 // generated code branches to key_not_smi. Callers can specify NULL for | 464 kFPURegisters, |
493 // key_not_smi to signal that a smi check has already been performed on key so | 465 kCoreRegisters |
494 // that the smi check is not generated . If key is not a valid index within the | 466 }; |
495 // bounds of the pixel array, the generated code jumps to out_of_range. | 467 |
496 void GenerateFastPixelArrayLoad(MacroAssembler* masm, | 468 |
497 Register receiver, | 469 // Loads smis from a0 and a1 (right and left in binary operations) into |
498 Register key, | 470 // floating point registers. Depending on the destination the values ends up |
499 Register elements_map, | 471 // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination |
500 Register elements, | 472 // is floating point registers FPU must be supported. If core registers are |
| 473 // requested when FPU is supported f12 and f14 will be scratched. |
| 474 static void LoadSmis(MacroAssembler* masm, |
| 475 Destination destination, |
| 476 Register scratch1, |
| 477 Register scratch2); |
| 478 |
| 479 // Loads objects from a0 and a1 (right and left in binary operations) into |
| 480 // floating point registers. Depending on the destination the values ends up |
| 481 // either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination |
| 482 // is floating point registers FPU must be supported. If core registers are |
| 483 // requested when FPU is supported f12 and f14 will still be scratched. If |
| 484 // either a0 or a1 is not a number (not smi and not heap number object) the |
| 485 // not_number label is jumped to with a0 and a1 intact. |
| 486 static void LoadOperands(MacroAssembler* masm, |
| 487 FloatingPointHelper::Destination destination, |
| 488 Register heap_number_map, |
| 489 Register scratch1, |
| 490 Register scratch2, |
| 491 Label* not_number); |
| 492 |
| 493 // Convert the smi or heap number in object to an int32 using the rules |
| 494 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated |
| 495 // and brought into the range -2^31 .. +2^31 - 1. |
| 496 static void ConvertNumberToInt32(MacroAssembler* masm, |
| 497 Register object, |
| 498 Register dst, |
| 499 Register heap_number_map, |
| 500 Register scratch1, |
| 501 Register scratch2, |
| 502 Register scratch3, |
| 503 FPURegister double_scratch, |
| 504 Label* not_int32); |
| 505 |
| 506 // Converts the integer (untagged smi) in |int_scratch| to a double, storing |
| 507 // the result either in |double_dst| or |dst2:dst1|, depending on |
| 508 // |destination|. |
| 509 // Warning: The value in |int_scratch| will be changed in the process! |
| 510 static void ConvertIntToDouble(MacroAssembler* masm, |
| 511 Register int_scratch, |
| 512 Destination destination, |
| 513 FPURegister double_dst, |
| 514 Register dst1, |
| 515 Register dst2, |
| 516 Register scratch2, |
| 517 FPURegister single_scratch); |
| 518 |
| 519 // Load the number from object into double_dst in the double format. |
| 520 // Control will jump to not_int32 if the value cannot be exactly represented |
| 521 // by a 32-bit integer. |
| 522 // Floating point value in the 32-bit integer range that are not exact integer |
| 523 // won't be loaded. |
| 524 static void LoadNumberAsInt32Double(MacroAssembler* masm, |
| 525 Register object, |
| 526 Destination destination, |
| 527 FPURegister double_dst, |
| 528 Register dst1, |
| 529 Register dst2, |
| 530 Register heap_number_map, |
| 531 Register scratch1, |
| 532 Register scratch2, |
| 533 FPURegister single_scratch, |
| 534 Label* not_int32); |
| 535 |
| 536 // Loads the number from object into dst as a 32-bit integer. |
| 537 // Control will jump to not_int32 if the object cannot be exactly represented |
| 538 // by a 32-bit integer. |
| 539 // Floating point value in the 32-bit integer range that are not exact integer |
| 540 // won't be converted. |
| 541 // scratch3 is not used when FPU is supported. |
| 542 static void LoadNumberAsInt32(MacroAssembler* masm, |
| 543 Register object, |
| 544 Register dst, |
| 545 Register heap_number_map, |
501 Register scratch1, | 546 Register scratch1, |
502 Register scratch2, | 547 Register scratch2, |
503 Register result, | 548 Register scratch3, |
504 Label* not_pixel_array, | 549 FPURegister double_scratch, |
505 Label* key_not_smi, | 550 Label* not_int32); |
506 Label* out_of_range); | 551 |
| 552 // Generate non FPU code to check if a double can be exactly represented by a |
| 553 // 32-bit integer. This does not check for 0 or -0, which need |
| 554 // to be checked for separately. |
| 555 // Control jumps to not_int32 if the value is not a 32-bit integer, and falls |
| 556 // through otherwise. |
| 557 // src1 and src2 will be cloberred. |
| 558 // |
| 559 // Expected input: |
| 560 // - src1: higher (exponent) part of the double value. |
| 561 // - src2: lower (mantissa) part of the double value. |
| 562 // Output status: |
| 563 // - dst: 32 higher bits of the mantissa. (mantissa[51:20]) |
| 564 // - src2: contains 1. |
| 565 // - other registers are clobbered. |
| 566 static void DoubleIs32BitInteger(MacroAssembler* masm, |
| 567 Register src1, |
| 568 Register src2, |
| 569 Register dst, |
| 570 Register scratch, |
| 571 Label* not_int32); |
| 572 |
| 573 // Generates code to call a C function to do a double operation using core |
| 574 // registers. (Used when FPU is not supported.) |
| 575 // This code never falls through, but returns with a heap number containing |
| 576 // the result in v0. |
| 577 // Register heapnumber_result must be a heap number in which the |
| 578 // result of the operation will be stored. |
| 579 // Requires the following layout on entry: |
| 580 // a0: Left value (least significant part of mantissa). |
| 581 // a1: Left value (sign, exponent, top of mantissa). |
| 582 // a2: Right value (least significant part of mantissa). |
| 583 // a3: Right value (sign, exponent, top of mantissa). |
| 584 static void CallCCodeForDoubleOperation(MacroAssembler* masm, |
| 585 Token::Value op, |
| 586 Register heap_number_result, |
| 587 Register scratch); |
| 588 |
| 589 private: |
| 590 static void LoadNumber(MacroAssembler* masm, |
| 591 FloatingPointHelper::Destination destination, |
| 592 Register object, |
| 593 FPURegister dst, |
| 594 Register dst1, |
| 595 Register dst2, |
| 596 Register heap_number_map, |
| 597 Register scratch1, |
| 598 Register scratch2, |
| 599 Label* not_number); |
| 600 }; |
| 601 |
| 602 |
| 603 class StringDictionaryLookupStub: public CodeStub { |
| 604 public: |
| 605 enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP }; |
| 606 |
| 607 explicit StringDictionaryLookupStub(LookupMode mode) : mode_(mode) { } |
| 608 |
| 609 void Generate(MacroAssembler* masm); |
| 610 |
| 611 static void GenerateNegativeLookup(MacroAssembler* masm, |
| 612 Label* miss, |
| 613 Label* done, |
| 614 Register receiver, |
| 615 Register properties, |
| 616 String* name, |
| 617 Register scratch0) ; |
| 618 |
| 619 static void GeneratePositiveLookup(MacroAssembler* masm, |
| 620 Label* miss, |
| 621 Label* done, |
| 622 Register elements, |
| 623 Register name, |
| 624 Register r0, |
| 625 Register r1); |
| 626 |
| 627 private: |
| 628 static const int kInlinedProbes = 4; |
| 629 static const int kTotalProbes = 20; |
| 630 |
| 631 static const int kCapacityOffset = |
| 632 StringDictionary::kHeaderSize + |
| 633 StringDictionary::kCapacityIndex * kPointerSize; |
| 634 |
| 635 static const int kElementsStartOffset = |
| 636 StringDictionary::kHeaderSize + |
| 637 StringDictionary::kElementsStartIndex * kPointerSize; |
| 638 |
| 639 |
| 640 #ifdef DEBUG |
| 641 void Print() { |
| 642 PrintF("StringDictionaryLookupStub\n"); |
| 643 } |
| 644 #endif |
| 645 |
| 646 Major MajorKey() { return StringDictionaryNegativeLookup; } |
| 647 |
| 648 int MinorKey() { |
| 649 return LookupModeBits::encode(mode_); |
| 650 } |
| 651 |
| 652 class LookupModeBits: public BitField<LookupMode, 0, 1> {}; |
| 653 |
| 654 LookupMode mode_; |
| 655 }; |
507 | 656 |
508 | 657 |
509 } } // namespace v8::internal | 658 } } // namespace v8::internal |
510 | 659 |
511 #endif // V8_MIPS_CODE_STUBS_ARM_H_ | 660 #endif // V8_MIPS_CODE_STUBS_ARM_H_ |
OLD | NEW |