blob: cdea03ee8aafadf3a9ed4266e3892f2fdbbaf946 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Kristian Monsen80d68ea2010-09-08 11:05:35 +01002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_ARM_CODE_STUBS_ARM_H_
29#define V8_ARM_CODE_STUBS_ARM_H_
30
31#include "ic-inl.h"
32
33namespace v8 {
34namespace internal {
35
36
37// Compute a transcendental math function natively, or call the
38// TranscendentalCache runtime function.
39class TranscendentalCacheStub: public CodeStub {
40 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +010041 enum ArgumentType {
42 TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits,
43 UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
44 };
45
46 TranscendentalCacheStub(TranscendentalCache::Type type,
47 ArgumentType argument_type)
48 : type_(type), argument_type_(argument_type) { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +010049 void Generate(MacroAssembler* masm);
50 private:
51 TranscendentalCache::Type type_;
Ben Murdoche0cee9b2011-05-25 10:26:03 +010052 ArgumentType argument_type_;
53 void GenerateCallCFunction(MacroAssembler* masm, Register scratch);
54
Kristian Monsen80d68ea2010-09-08 11:05:35 +010055 Major MajorKey() { return TranscendentalCache; }
Ben Murdoche0cee9b2011-05-25 10:26:03 +010056 int MinorKey() { return type_ | argument_type_; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +010057 Runtime::FunctionId RuntimeFunction();
58};
59
60
Ben Murdoch257744e2011-11-30 15:57:28 +000061class UnaryOpStub: public CodeStub {
Steve Block1e0659c2011-05-24 12:43:12 +010062 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000063 UnaryOpStub(Token::Value op,
64 UnaryOverwriteMode mode,
65 UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
Steve Block1e0659c2011-05-24 12:43:12 +010066 : op_(op),
67 mode_(mode),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000068 operand_type_(operand_type) {
Ben Murdoch257744e2011-11-30 15:57:28 +000069 }
70
71 private:
72 Token::Value op_;
73 UnaryOverwriteMode mode_;
74
75 // Operand type information determined at runtime.
76 UnaryOpIC::TypeInfo operand_type_;
77
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000078 virtual void PrintName(StringStream* stream);
Ben Murdoch257744e2011-11-30 15:57:28 +000079
80 class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
81 class OpBits: public BitField<Token::Value, 1, 7> {};
82 class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
83
84 Major MajorKey() { return UnaryOp; }
85 int MinorKey() {
86 return ModeBits::encode(mode_)
87 | OpBits::encode(op_)
88 | OperandTypeInfoBits::encode(operand_type_);
89 }
90
91 // Note: A lot of the helper functions below will vanish when we use virtual
92 // function instead of switch more often.
93 void Generate(MacroAssembler* masm);
94
95 void GenerateTypeTransition(MacroAssembler* masm);
96
97 void GenerateSmiStub(MacroAssembler* masm);
98 void GenerateSmiStubSub(MacroAssembler* masm);
99 void GenerateSmiStubBitNot(MacroAssembler* masm);
100 void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
101 void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
102
103 void GenerateHeapNumberStub(MacroAssembler* masm);
104 void GenerateHeapNumberStubSub(MacroAssembler* masm);
105 void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
106 void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
107 void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
108
109 void GenerateGenericStub(MacroAssembler* masm);
110 void GenerateGenericStubSub(MacroAssembler* masm);
111 void GenerateGenericStubBitNot(MacroAssembler* masm);
112 void GenerateGenericCodeFallback(MacroAssembler* masm);
113
114 virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
115
116 virtual InlineCacheState GetICState() {
117 return UnaryOpIC::ToState(operand_type_);
118 }
119
120 virtual void FinishCode(Code* code) {
121 code->set_unary_op_type(operand_type_);
122 }
123};
124
125
126class BinaryOpStub: public CodeStub {
127 public:
128 BinaryOpStub(Token::Value op, OverwriteMode mode)
129 : op_(op),
130 mode_(mode),
131 operands_type_(BinaryOpIC::UNINITIALIZED),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000132 result_type_(BinaryOpIC::UNINITIALIZED) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100133 use_vfp3_ = CpuFeatures::IsSupported(VFP3);
Steve Block1e0659c2011-05-24 12:43:12 +0100134 ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
135 }
136
Ben Murdoch257744e2011-11-30 15:57:28 +0000137 BinaryOpStub(
Steve Block1e0659c2011-05-24 12:43:12 +0100138 int key,
Ben Murdoch257744e2011-11-30 15:57:28 +0000139 BinaryOpIC::TypeInfo operands_type,
140 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
Steve Block1e0659c2011-05-24 12:43:12 +0100141 : op_(OpBits::decode(key)),
142 mode_(ModeBits::decode(key)),
143 use_vfp3_(VFP3Bits::decode(key)),
144 operands_type_(operands_type),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000145 result_type_(result_type) { }
Steve Block1e0659c2011-05-24 12:43:12 +0100146
147 private:
148 enum SmiCodeGenerateHeapNumberResults {
149 ALLOW_HEAPNUMBER_RESULTS,
150 NO_HEAPNUMBER_RESULTS
151 };
152
153 Token::Value op_;
154 OverwriteMode mode_;
155 bool use_vfp3_;
156
157 // Operand type information determined at runtime.
Ben Murdoch257744e2011-11-30 15:57:28 +0000158 BinaryOpIC::TypeInfo operands_type_;
159 BinaryOpIC::TypeInfo result_type_;
Steve Block1e0659c2011-05-24 12:43:12 +0100160
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000161 virtual void PrintName(StringStream* stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100162
163 // Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
164 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
165 class OpBits: public BitField<Token::Value, 2, 7> {};
166 class VFP3Bits: public BitField<bool, 9, 1> {};
Ben Murdoch257744e2011-11-30 15:57:28 +0000167 class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
168 class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
Steve Block1e0659c2011-05-24 12:43:12 +0100169
Ben Murdoch257744e2011-11-30 15:57:28 +0000170 Major MajorKey() { return BinaryOp; }
Steve Block1e0659c2011-05-24 12:43:12 +0100171 int MinorKey() {
172 return OpBits::encode(op_)
173 | ModeBits::encode(mode_)
174 | VFP3Bits::encode(use_vfp3_)
175 | OperandTypeInfoBits::encode(operands_type_)
176 | ResultTypeInfoBits::encode(result_type_);
177 }
178
179 void Generate(MacroAssembler* masm);
180 void GenerateGeneric(MacroAssembler* masm);
181 void GenerateSmiSmiOperation(MacroAssembler* masm);
182 void GenerateFPOperation(MacroAssembler* masm,
183 bool smi_operands,
184 Label* not_numbers,
185 Label* gc_required);
186 void GenerateSmiCode(MacroAssembler* masm,
Ben Murdoch8b112d22011-06-08 16:22:53 +0100187 Label* use_runtime,
Steve Block1e0659c2011-05-24 12:43:12 +0100188 Label* gc_required,
189 SmiCodeGenerateHeapNumberResults heapnumber_results);
190 void GenerateLoadArguments(MacroAssembler* masm);
191 void GenerateReturn(MacroAssembler* masm);
192 void GenerateUninitializedStub(MacroAssembler* masm);
193 void GenerateSmiStub(MacroAssembler* masm);
194 void GenerateInt32Stub(MacroAssembler* masm);
195 void GenerateHeapNumberStub(MacroAssembler* masm);
Steve Block44f0eee2011-05-26 01:26:41 +0100196 void GenerateOddballStub(MacroAssembler* masm);
Steve Block1e0659c2011-05-24 12:43:12 +0100197 void GenerateStringStub(MacroAssembler* masm);
Ben Murdoch257744e2011-11-30 15:57:28 +0000198 void GenerateBothStringStub(MacroAssembler* masm);
Steve Block1e0659c2011-05-24 12:43:12 +0100199 void GenerateGenericStub(MacroAssembler* masm);
200 void GenerateAddStrings(MacroAssembler* masm);
201 void GenerateCallRuntime(MacroAssembler* masm);
202
203 void GenerateHeapResultAllocation(MacroAssembler* masm,
204 Register result,
205 Register heap_number_map,
206 Register scratch1,
207 Register scratch2,
208 Label* gc_required);
209 void GenerateRegisterArgsPush(MacroAssembler* masm);
210 void GenerateTypeTransition(MacroAssembler* masm);
211 void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
212
Ben Murdoch257744e2011-11-30 15:57:28 +0000213 virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
Steve Block1e0659c2011-05-24 12:43:12 +0100214
215 virtual InlineCacheState GetICState() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000216 return BinaryOpIC::ToState(operands_type_);
Steve Block1e0659c2011-05-24 12:43:12 +0100217 }
218
219 virtual void FinishCode(Code* code) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000220 code->set_binary_op_type(operands_type_);
221 code->set_binary_op_result_type(result_type_);
Steve Block1e0659c2011-05-24 12:43:12 +0100222 }
223
224 friend class CodeGenerator;
225};
226
227
Ben Murdoch692be652012-01-10 18:47:50 +0000228class StringHelper : public AllStatic {
229 public:
230 // Generate code for copying characters using a simple loop. This should only
231 // be used in places where the number of characters is small and the
232 // additional setup and checking in GenerateCopyCharactersLong adds too much
233 // overhead. Copying of overlapping regions is not supported.
234 // Dest register ends at the position after the last character written.
235 static void GenerateCopyCharacters(MacroAssembler* masm,
236 Register dest,
237 Register src,
238 Register count,
239 Register scratch,
240 bool ascii);
241
242 // Generate code for copying a large number of characters. This function
243 // is allowed to spend extra time setting up conditions to make copying
244 // faster. Copying of overlapping regions is not supported.
245 // Dest register ends at the position after the last character written.
246 static void GenerateCopyCharactersLong(MacroAssembler* masm,
247 Register dest,
248 Register src,
249 Register count,
250 Register scratch1,
251 Register scratch2,
252 Register scratch3,
253 Register scratch4,
254 Register scratch5,
255 int flags);
256
257
258 // Probe the symbol table for a two character string. If the string is
259 // not found by probing a jump to the label not_found is performed. This jump
260 // does not guarantee that the string is not in the symbol table. If the
261 // string is found the code falls through with the string in register r0.
262 // Contents of both c1 and c2 registers are modified. At the exit c1 is
263 // guaranteed to contain halfword with low and high bytes equal to
264 // initial contents of c1 and c2 respectively.
265 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
266 Register c1,
267 Register c2,
268 Register scratch1,
269 Register scratch2,
270 Register scratch3,
271 Register scratch4,
272 Register scratch5,
273 Label* not_found);
274
275 // Generate string hash.
276 static void GenerateHashInit(MacroAssembler* masm,
277 Register hash,
278 Register character);
279
280 static void GenerateHashAddCharacter(MacroAssembler* masm,
281 Register hash,
282 Register character);
283
284 static void GenerateHashGetHash(MacroAssembler* masm,
285 Register hash);
286
287 private:
288 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
289};
290
291
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100292// Flag that indicates how to generate code for the stub StringAddStub.
293enum StringAddFlags {
294 NO_STRING_ADD_FLAGS = 0,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100295 // Omit left string check in stub (left is definitely a string).
296 NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
297 // Omit right string check in stub (right is definitely a string).
298 NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
299 // Omit both string checks in stub.
300 NO_STRING_CHECK_IN_STUB =
301 NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100302};
303
304
305class StringAddStub: public CodeStub {
306 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100307 explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100308
309 private:
310 Major MajorKey() { return StringAdd; }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100311 int MinorKey() { return flags_; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100312
313 void Generate(MacroAssembler* masm);
314
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100315 void GenerateConvertArgument(MacroAssembler* masm,
316 int stack_offset,
317 Register arg,
318 Register scratch1,
319 Register scratch2,
320 Register scratch3,
321 Register scratch4,
322 Label* slow);
323
324 const StringAddFlags flags_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100325};
326
327
328class SubStringStub: public CodeStub {
329 public:
330 SubStringStub() {}
331
332 private:
333 Major MajorKey() { return SubString; }
334 int MinorKey() { return 0; }
335
336 void Generate(MacroAssembler* masm);
337};
338
339
340
341class StringCompareStub: public CodeStub {
342 public:
343 StringCompareStub() { }
344
Ben Murdoch257744e2011-11-30 15:57:28 +0000345 // Compares two flat ASCII strings and returns result in r0.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100346 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
347 Register left,
348 Register right,
349 Register scratch1,
350 Register scratch2,
351 Register scratch3,
352 Register scratch4);
353
Ben Murdoch257744e2011-11-30 15:57:28 +0000354 // Compares two flat ASCII strings for equality and returns result
355 // in r0.
356 static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
357 Register left,
358 Register right,
359 Register scratch1,
360 Register scratch2,
361 Register scratch3);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100362
Ben Murdoch257744e2011-11-30 15:57:28 +0000363 private:
364 virtual Major MajorKey() { return StringCompare; }
365 virtual int MinorKey() { return 0; }
366 virtual void Generate(MacroAssembler* masm);
367
368 static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
369 Register left,
370 Register right,
371 Register length,
372 Register scratch1,
373 Register scratch2,
374 Label* chars_not_equal);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100375};
376
377
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100378// This stub can convert a signed int32 to a heap number (double). It does
379// not work for int32s that are in Smi range! No GC occurs during this stub
380// so you don't have to set up the frame.
381class WriteInt32ToHeapNumberStub : public CodeStub {
382 public:
383 WriteInt32ToHeapNumberStub(Register the_int,
384 Register the_heap_number,
385 Register scratch)
386 : the_int_(the_int),
387 the_heap_number_(the_heap_number),
388 scratch_(scratch) { }
389
390 private:
391 Register the_int_;
392 Register the_heap_number_;
393 Register scratch_;
394
395 // Minor key encoding in 16 bits.
396 class IntRegisterBits: public BitField<int, 0, 4> {};
397 class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
398 class ScratchRegisterBits: public BitField<int, 8, 4> {};
399
400 Major MajorKey() { return WriteInt32ToHeapNumber; }
401 int MinorKey() {
402 // Encode the parameters in a unique 16 bit value.
403 return IntRegisterBits::encode(the_int_.code())
404 | HeapNumberRegisterBits::encode(the_heap_number_.code())
405 | ScratchRegisterBits::encode(scratch_.code());
406 }
407
408 void Generate(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100409};
410
411
412class NumberToStringStub: public CodeStub {
413 public:
414 NumberToStringStub() { }
415
416 // Generate code to do a lookup in the number string cache. If the number in
417 // the register object is found in the cache the generated code falls through
418 // with the result in the result register. The object and the result register
419 // can be the same. If the number is not found in the cache the code jumps to
420 // the label not_found with only the content of register object unchanged.
421 static void GenerateLookupNumberStringCache(MacroAssembler* masm,
422 Register object,
423 Register result,
424 Register scratch1,
425 Register scratch2,
426 Register scratch3,
427 bool object_is_smi,
428 Label* not_found);
429
430 private:
431 Major MajorKey() { return NumberToString; }
432 int MinorKey() { return 0; }
433
434 void Generate(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100435};
436
437
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100438// Enter C code from generated RegExp code in a way that allows
439// the C code to fix the return address in case of a GC.
440// Currently only needed on ARM.
441class RegExpCEntryStub: public CodeStub {
442 public:
443 RegExpCEntryStub() {}
444 virtual ~RegExpCEntryStub() {}
445 void Generate(MacroAssembler* masm);
446
447 private:
448 Major MajorKey() { return RegExpCEntry; }
449 int MinorKey() { return 0; }
Steve Block44f0eee2011-05-26 01:26:41 +0100450
451 bool NeedsImmovableCode() { return true; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100452};
453
454
Steve Block1e0659c2011-05-24 12:43:12 +0100455// Trampoline stub to call into native code. To call safely into native code
456// in the presence of compacting GC (which can move code objects) we need to
457// keep the code which called into native pinned in the memory. Currently the
458// simplest approach is to generate such stub early enough so it can never be
459// moved by GC
460class DirectCEntryStub: public CodeStub {
461 public:
462 DirectCEntryStub() {}
463 void Generate(MacroAssembler* masm);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100464 void GenerateCall(MacroAssembler* masm, ExternalReference function);
465 void GenerateCall(MacroAssembler* masm, Register target);
Steve Block1e0659c2011-05-24 12:43:12 +0100466
467 private:
468 Major MajorKey() { return DirectCEntry; }
469 int MinorKey() { return 0; }
Steve Block44f0eee2011-05-26 01:26:41 +0100470
471 bool NeedsImmovableCode() { return true; }
Steve Block1e0659c2011-05-24 12:43:12 +0100472};
473
474
Ben Murdoch257744e2011-11-30 15:57:28 +0000475class FloatingPointHelper : public AllStatic {
476 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000477 enum Destination {
478 kVFPRegisters,
479 kCoreRegisters
480 };
481
482
483 // Loads smis from r0 and r1 (right and left in binary operations) into
484 // floating point registers. Depending on the destination the values ends up
485 // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is
486 // floating point registers VFP3 must be supported. If core registers are
487 // requested when VFP3 is supported d6 and d7 will be scratched.
488 static void LoadSmis(MacroAssembler* masm,
489 Destination destination,
490 Register scratch1,
491 Register scratch2);
492
493 // Loads objects from r0 and r1 (right and left in binary operations) into
494 // floating point registers. Depending on the destination the values ends up
495 // either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is
496 // floating point registers VFP3 must be supported. If core registers are
497 // requested when VFP3 is supported d6 and d7 will still be scratched. If
498 // either r0 or r1 is not a number (not smi and not heap number object) the
499 // not_number label is jumped to with r0 and r1 intact.
500 static void LoadOperands(MacroAssembler* masm,
501 FloatingPointHelper::Destination destination,
502 Register heap_number_map,
503 Register scratch1,
504 Register scratch2,
505 Label* not_number);
506
507 // Convert the smi or heap number in object to an int32 using the rules
508 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
509 // and brought into the range -2^31 .. +2^31 - 1.
510 static void ConvertNumberToInt32(MacroAssembler* masm,
511 Register object,
512 Register dst,
513 Register heap_number_map,
514 Register scratch1,
515 Register scratch2,
516 Register scratch3,
517 DwVfpRegister double_scratch,
518 Label* not_int32);
519
520 // Converts the integer (untagged smi) in |int_scratch| to a double, storing
521 // the result either in |double_dst| or |dst2:dst1|, depending on
522 // |destination|.
523 // Warning: The value in |int_scratch| will be changed in the process!
524 static void ConvertIntToDouble(MacroAssembler* masm,
525 Register int_scratch,
526 Destination destination,
527 DwVfpRegister double_dst,
528 Register dst1,
529 Register dst2,
530 Register scratch2,
531 SwVfpRegister single_scratch);
532
533 // Load the number from object into double_dst in the double format.
534 // Control will jump to not_int32 if the value cannot be exactly represented
535 // by a 32-bit integer.
536 // Floating point value in the 32-bit integer range that are not exact integer
537 // won't be loaded.
538 static void LoadNumberAsInt32Double(MacroAssembler* masm,
539 Register object,
540 Destination destination,
541 DwVfpRegister double_dst,
542 Register dst1,
543 Register dst2,
544 Register heap_number_map,
545 Register scratch1,
546 Register scratch2,
547 SwVfpRegister single_scratch,
548 Label* not_int32);
549
550 // Loads the number from object into dst as a 32-bit integer.
551 // Control will jump to not_int32 if the object cannot be exactly represented
552 // by a 32-bit integer.
553 // Floating point value in the 32-bit integer range that are not exact integer
554 // won't be converted.
555 // scratch3 is not used when VFP3 is supported.
556 static void LoadNumberAsInt32(MacroAssembler* masm,
557 Register object,
558 Register dst,
559 Register heap_number_map,
560 Register scratch1,
561 Register scratch2,
562 Register scratch3,
563 DwVfpRegister double_scratch,
564 Label* not_int32);
565
566 // Generate non VFP3 code to check if a double can be exactly represented by a
567 // 32-bit integer. This does not check for 0 or -0, which need
568 // to be checked for separately.
569 // Control jumps to not_int32 if the value is not a 32-bit integer, and falls
570 // through otherwise.
571 // src1 and src2 will be cloberred.
572 //
573 // Expected input:
574 // - src1: higher (exponent) part of the double value.
575 // - src2: lower (mantissa) part of the double value.
576 // Output status:
577 // - dst: 32 higher bits of the mantissa. (mantissa[51:20])
578 // - src2: contains 1.
579 // - other registers are clobbered.
580 static void DoubleIs32BitInteger(MacroAssembler* masm,
581 Register src1,
582 Register src2,
583 Register dst,
584 Register scratch,
585 Label* not_int32);
586
587 // Generates code to call a C function to do a double operation using core
588 // registers. (Used when VFP3 is not supported.)
589 // This code never falls through, but returns with a heap number containing
590 // the result in r0.
591 // Register heapnumber_result must be a heap number in which the
592 // result of the operation will be stored.
593 // Requires the following layout on entry:
594 // r0: Left value (least significant part of mantissa).
595 // r1: Left value (sign, exponent, top of mantissa).
596 // r2: Right value (least significant part of mantissa).
597 // r3: Right value (sign, exponent, top of mantissa).
598 static void CallCCodeForDoubleOperation(MacroAssembler* masm,
599 Token::Value op,
600 Register heap_number_result,
601 Register scratch);
602
603 private:
604 static void LoadNumber(MacroAssembler* masm,
605 FloatingPointHelper::Destination destination,
606 Register object,
607 DwVfpRegister dst,
608 Register dst1,
609 Register dst2,
610 Register heap_number_map,
611 Register scratch1,
612 Register scratch2,
613 Label* not_number);
614};
615
616
617class StringDictionaryLookupStub: public CodeStub {
618 public:
619 enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
620
621 explicit StringDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
622
623 void Generate(MacroAssembler* masm);
624
625 MUST_USE_RESULT static MaybeObject* GenerateNegativeLookup(
626 MacroAssembler* masm,
627 Label* miss,
628 Label* done,
629 Register receiver,
630 Register properties,
631 String* name,
632 Register scratch0);
633
634 static void GeneratePositiveLookup(MacroAssembler* masm,
635 Label* miss,
636 Label* done,
637 Register elements,
638 Register name,
639 Register r0,
640 Register r1);
641
642 private:
643 static const int kInlinedProbes = 4;
644 static const int kTotalProbes = 20;
645
646 static const int kCapacityOffset =
647 StringDictionary::kHeaderSize +
648 StringDictionary::kCapacityIndex * kPointerSize;
649
650 static const int kElementsStartOffset =
651 StringDictionary::kHeaderSize +
652 StringDictionary::kElementsStartIndex * kPointerSize;
653
Ben Murdoch257744e2011-11-30 15:57:28 +0000654 Major MajorKey() { return StringDictionaryNegativeLookup; }
655
656 int MinorKey() {
657 return LookupModeBits::encode(mode_);
658 }
659
660 class LookupModeBits: public BitField<LookupMode, 0, 1> {};
661
662 LookupMode mode_;
663};
664
665
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100666} } // namespace v8::internal
667
668#endif // V8_ARM_CODE_STUBS_ARM_H_