code-stubs-arm.h revision 053d10c438f14580aaf4ab1b2aad93a5a4fe8b82
1// Copyright 2010 the V8 project authors. All rights reserved.
2// 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:
41  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) { }
49  void Generate(MacroAssembler* masm);
50 private:
51  TranscendentalCache::Type type_;
52  ArgumentType argument_type_;
53  void GenerateCallCFunction(MacroAssembler* masm, Register scratch);
54
55  Major MajorKey() { return TranscendentalCache; }
56  int MinorKey() { return type_ | argument_type_; }
57  Runtime::FunctionId RuntimeFunction();
58};
59
60
61class ToBooleanStub: public CodeStub {
62 public:
63  explicit ToBooleanStub(Register tos) : tos_(tos) { }
64
65  void Generate(MacroAssembler* masm);
66
67 private:
68  Register tos_;
69  Major MajorKey() { return ToBoolean; }
70  int MinorKey() { return tos_.code(); }
71};
72
73
74class TypeRecordingBinaryOpStub: public CodeStub {
75 public:
76  TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
77      : op_(op),
78        mode_(mode),
79        operands_type_(TRBinaryOpIC::UNINITIALIZED),
80        result_type_(TRBinaryOpIC::UNINITIALIZED),
81        name_(NULL) {
82    use_vfp3_ = CpuFeatures::IsSupported(VFP3);
83    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
84  }
85
86  TypeRecordingBinaryOpStub(
87      int key,
88      TRBinaryOpIC::TypeInfo operands_type,
89      TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
90      : op_(OpBits::decode(key)),
91        mode_(ModeBits::decode(key)),
92        use_vfp3_(VFP3Bits::decode(key)),
93        operands_type_(operands_type),
94        result_type_(result_type),
95        name_(NULL) { }
96
97 private:
98  enum SmiCodeGenerateHeapNumberResults {
99    ALLOW_HEAPNUMBER_RESULTS,
100    NO_HEAPNUMBER_RESULTS
101  };
102
103  Token::Value op_;
104  OverwriteMode mode_;
105  bool use_vfp3_;
106
107  // Operand type information determined at runtime.
108  TRBinaryOpIC::TypeInfo operands_type_;
109  TRBinaryOpIC::TypeInfo result_type_;
110
111  char* name_;
112
113  const char* GetName();
114
115#ifdef DEBUG
116  void Print() {
117    PrintF("TypeRecordingBinaryOpStub %d (op %s), "
118           "(mode %d, runtime_type_info %s)\n",
119           MinorKey(),
120           Token::String(op_),
121           static_cast<int>(mode_),
122           TRBinaryOpIC::GetName(operands_type_));
123  }
124#endif
125
126  // Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
127  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
128  class OpBits: public BitField<Token::Value, 2, 7> {};
129  class VFP3Bits: public BitField<bool, 9, 1> {};
130  class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 10, 3> {};
131  class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 13, 3> {};
132
133  Major MajorKey() { return TypeRecordingBinaryOp; }
134  int MinorKey() {
135    return OpBits::encode(op_)
136           | ModeBits::encode(mode_)
137           | VFP3Bits::encode(use_vfp3_)
138           | OperandTypeInfoBits::encode(operands_type_)
139           | ResultTypeInfoBits::encode(result_type_);
140  }
141
142  void Generate(MacroAssembler* masm);
143  void GenerateGeneric(MacroAssembler* masm);
144  void GenerateSmiSmiOperation(MacroAssembler* masm);
145  void GenerateFPOperation(MacroAssembler* masm,
146                           bool smi_operands,
147                           Label* not_numbers,
148                           Label* gc_required);
149  void GenerateSmiCode(MacroAssembler* masm,
150                       Label* use_runtime,
151                       Label* gc_required,
152                       SmiCodeGenerateHeapNumberResults heapnumber_results);
153  void GenerateLoadArguments(MacroAssembler* masm);
154  void GenerateReturn(MacroAssembler* masm);
155  void GenerateUninitializedStub(MacroAssembler* masm);
156  void GenerateSmiStub(MacroAssembler* masm);
157  void GenerateInt32Stub(MacroAssembler* masm);
158  void GenerateHeapNumberStub(MacroAssembler* masm);
159  void GenerateOddballStub(MacroAssembler* masm);
160  void GenerateStringStub(MacroAssembler* masm);
161  void GenerateGenericStub(MacroAssembler* masm);
162  void GenerateAddStrings(MacroAssembler* masm);
163  void GenerateCallRuntime(MacroAssembler* masm);
164
165  void GenerateHeapResultAllocation(MacroAssembler* masm,
166                                    Register result,
167                                    Register heap_number_map,
168                                    Register scratch1,
169                                    Register scratch2,
170                                    Label* gc_required);
171  void GenerateRegisterArgsPush(MacroAssembler* masm);
172  void GenerateTypeTransition(MacroAssembler* masm);
173  void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
174
175  virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
176
177  virtual InlineCacheState GetICState() {
178    return TRBinaryOpIC::ToState(operands_type_);
179  }
180
181  virtual void FinishCode(Code* code) {
182    code->set_type_recording_binary_op_type(operands_type_);
183    code->set_type_recording_binary_op_result_type(result_type_);
184  }
185
186  friend class CodeGenerator;
187};
188
189
190// Flag that indicates how to generate code for the stub StringAddStub.
191enum StringAddFlags {
192  NO_STRING_ADD_FLAGS = 0,
193  // Omit left string check in stub (left is definitely a string).
194  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
195  // Omit right string check in stub (right is definitely a string).
196  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
197  // Omit both string checks in stub.
198  NO_STRING_CHECK_IN_STUB =
199      NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
200};
201
202
203class StringAddStub: public CodeStub {
204 public:
205  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
206
207 private:
208  Major MajorKey() { return StringAdd; }
209  int MinorKey() { return flags_; }
210
211  void Generate(MacroAssembler* masm);
212
213  void GenerateConvertArgument(MacroAssembler* masm,
214                               int stack_offset,
215                               Register arg,
216                               Register scratch1,
217                               Register scratch2,
218                               Register scratch3,
219                               Register scratch4,
220                               Label* slow);
221
222  const StringAddFlags flags_;
223};
224
225
226class SubStringStub: public CodeStub {
227 public:
228  SubStringStub() {}
229
230 private:
231  Major MajorKey() { return SubString; }
232  int MinorKey() { return 0; }
233
234  void Generate(MacroAssembler* masm);
235};
236
237
238
239class StringCompareStub: public CodeStub {
240 public:
241  StringCompareStub() { }
242
243  // Compare two flat ASCII strings and returns result in r0.
244  // Does not use the stack.
245  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
246                                              Register left,
247                                              Register right,
248                                              Register scratch1,
249                                              Register scratch2,
250                                              Register scratch3,
251                                              Register scratch4);
252
253 private:
254  Major MajorKey() { return StringCompare; }
255  int MinorKey() { return 0; }
256
257  void Generate(MacroAssembler* masm);
258};
259
260
261// This stub can convert a signed int32 to a heap number (double).  It does
262// not work for int32s that are in Smi range!  No GC occurs during this stub
263// so you don't have to set up the frame.
264class WriteInt32ToHeapNumberStub : public CodeStub {
265 public:
266  WriteInt32ToHeapNumberStub(Register the_int,
267                             Register the_heap_number,
268                             Register scratch)
269      : the_int_(the_int),
270        the_heap_number_(the_heap_number),
271        scratch_(scratch) { }
272
273 private:
274  Register the_int_;
275  Register the_heap_number_;
276  Register scratch_;
277
278  // Minor key encoding in 16 bits.
279  class IntRegisterBits: public BitField<int, 0, 4> {};
280  class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
281  class ScratchRegisterBits: public BitField<int, 8, 4> {};
282
283  Major MajorKey() { return WriteInt32ToHeapNumber; }
284  int MinorKey() {
285    // Encode the parameters in a unique 16 bit value.
286    return IntRegisterBits::encode(the_int_.code())
287           | HeapNumberRegisterBits::encode(the_heap_number_.code())
288           | ScratchRegisterBits::encode(scratch_.code());
289  }
290
291  void Generate(MacroAssembler* masm);
292
293  const char* GetName() { return "WriteInt32ToHeapNumberStub"; }
294
295#ifdef DEBUG
296  void Print() { PrintF("WriteInt32ToHeapNumberStub\n"); }
297#endif
298};
299
300
301class NumberToStringStub: public CodeStub {
302 public:
303  NumberToStringStub() { }
304
305  // Generate code to do a lookup in the number string cache. If the number in
306  // the register object is found in the cache the generated code falls through
307  // with the result in the result register. The object and the result register
308  // can be the same. If the number is not found in the cache the code jumps to
309  // the label not_found with only the content of register object unchanged.
310  static void GenerateLookupNumberStringCache(MacroAssembler* masm,
311                                              Register object,
312                                              Register result,
313                                              Register scratch1,
314                                              Register scratch2,
315                                              Register scratch3,
316                                              bool object_is_smi,
317                                              Label* not_found);
318
319 private:
320  Major MajorKey() { return NumberToString; }
321  int MinorKey() { return 0; }
322
323  void Generate(MacroAssembler* masm);
324
325  const char* GetName() { return "NumberToStringStub"; }
326};
327
328
329// Enter C code from generated RegExp code in a way that allows
330// the C code to fix the return address in case of a GC.
331// Currently only needed on ARM.
332class RegExpCEntryStub: public CodeStub {
333 public:
334  RegExpCEntryStub() {}
335  virtual ~RegExpCEntryStub() {}
336  void Generate(MacroAssembler* masm);
337
338 private:
339  Major MajorKey() { return RegExpCEntry; }
340  int MinorKey() { return 0; }
341
342  bool NeedsImmovableCode() { return true; }
343
344  const char* GetName() { return "RegExpCEntryStub"; }
345};
346
347
348// Trampoline stub to call into native code. To call safely into native code
349// in the presence of compacting GC (which can move code objects) we need to
350// keep the code which called into native pinned in the memory. Currently the
351// simplest approach is to generate such stub early enough so it can never be
352// moved by GC
353class DirectCEntryStub: public CodeStub {
354 public:
355  DirectCEntryStub() {}
356  void Generate(MacroAssembler* masm);
357  void GenerateCall(MacroAssembler* masm, ExternalReference function);
358  void GenerateCall(MacroAssembler* masm, Register target);
359
360 private:
361  Major MajorKey() { return DirectCEntry; }
362  int MinorKey() { return 0; }
363
364  bool NeedsImmovableCode() { return true; }
365
366  const char* GetName() { return "DirectCEntryStub"; }
367};
368
369
370} }  // namespace v8::internal
371
372#endif  // V8_ARM_CODE_STUBS_ARM_H_
373