blob: acf4a6f94879968fc4629389f7f2d756383e844d [file] [log] [blame]
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001// 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_IA32_CODE_STUBS_IA32_H_
29#define V8_IA32_CODE_STUBS_IA32_H_
30
31#include "macro-assembler.h"
32#include "code-stubs.h"
33#include "ic-inl.h"
34
35namespace v8 {
36namespace internal {
37
38
39// Compute a transcendental math function natively, or call the
40// TranscendentalCache runtime function.
41class TranscendentalCacheStub: public CodeStub {
42 public:
43 explicit TranscendentalCacheStub(TranscendentalCache::Type type)
44 : type_(type) {}
45 void Generate(MacroAssembler* masm);
46 private:
47 TranscendentalCache::Type type_;
48 Major MajorKey() { return TranscendentalCache; }
49 int MinorKey() { return type_; }
50 Runtime::FunctionId RuntimeFunction();
51 void GenerateOperation(MacroAssembler* masm);
52};
53
54
55class ToBooleanStub: public CodeStub {
56 public:
57 ToBooleanStub() { }
58
59 void Generate(MacroAssembler* masm);
60
61 private:
62 Major MajorKey() { return ToBoolean; }
63 int MinorKey() { return 0; }
64};
65
66
67// Flag that indicates how to generate code for the stub GenericBinaryOpStub.
68enum GenericBinaryFlags {
69 NO_GENERIC_BINARY_FLAGS = 0,
70 NO_SMI_CODE_IN_STUB = 1 << 0 // Omit smi code in stub.
71};
72
73
74class GenericBinaryOpStub: public CodeStub {
75 public:
76 GenericBinaryOpStub(Token::Value op,
77 OverwriteMode mode,
78 GenericBinaryFlags flags,
79 TypeInfo operands_type)
80 : op_(op),
81 mode_(mode),
82 flags_(flags),
83 args_in_registers_(false),
84 args_reversed_(false),
85 static_operands_type_(operands_type),
86 runtime_operands_type_(BinaryOpIC::DEFAULT),
87 name_(NULL) {
88 if (static_operands_type_.IsSmi()) {
89 mode_ = NO_OVERWRITE;
90 }
91 use_sse3_ = CpuFeatures::IsSupported(SSE3);
92 ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
93 }
94
95 GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo runtime_operands_type)
96 : op_(OpBits::decode(key)),
97 mode_(ModeBits::decode(key)),
98 flags_(FlagBits::decode(key)),
99 args_in_registers_(ArgsInRegistersBits::decode(key)),
100 args_reversed_(ArgsReversedBits::decode(key)),
101 use_sse3_(SSE3Bits::decode(key)),
102 static_operands_type_(TypeInfo::ExpandedRepresentation(
103 StaticTypeInfoBits::decode(key))),
104 runtime_operands_type_(runtime_operands_type),
105 name_(NULL) {
106 }
107
108 // Generate code to call the stub with the supplied arguments. This will add
109 // code at the call site to prepare arguments either in registers or on the
110 // stack together with the actual call.
111 void GenerateCall(MacroAssembler* masm, Register left, Register right);
112 void GenerateCall(MacroAssembler* masm, Register left, Smi* right);
113 void GenerateCall(MacroAssembler* masm, Smi* left, Register right);
114
115 bool ArgsInRegistersSupported() {
116 return op_ == Token::ADD || op_ == Token::SUB
117 || op_ == Token::MUL || op_ == Token::DIV;
118 }
119
120 private:
121 Token::Value op_;
122 OverwriteMode mode_;
123 GenericBinaryFlags flags_;
124 bool args_in_registers_; // Arguments passed in registers not on the stack.
125 bool args_reversed_; // Left and right argument are swapped.
126 bool use_sse3_;
127
128 // Number type information of operands, determined by code generator.
129 TypeInfo static_operands_type_;
130
131 // Operand type information determined at runtime.
132 BinaryOpIC::TypeInfo runtime_operands_type_;
133
134 char* name_;
135
136 const char* GetName();
137
138#ifdef DEBUG
139 void Print() {
140 PrintF("GenericBinaryOpStub %d (op %s), "
141 "(mode %d, flags %d, registers %d, reversed %d, type_info %s)\n",
142 MinorKey(),
143 Token::String(op_),
144 static_cast<int>(mode_),
145 static_cast<int>(flags_),
146 static_cast<int>(args_in_registers_),
147 static_cast<int>(args_reversed_),
148 static_operands_type_.ToString());
149 }
150#endif
151
152 // Minor key encoding in 18 bits RRNNNFRASOOOOOOOMM.
153 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
154 class OpBits: public BitField<Token::Value, 2, 7> {};
155 class SSE3Bits: public BitField<bool, 9, 1> {};
156 class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
157 class ArgsReversedBits: public BitField<bool, 11, 1> {};
158 class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
159 class StaticTypeInfoBits: public BitField<int, 13, 3> {};
160 class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 16, 2> {};
161
162 Major MajorKey() { return GenericBinaryOp; }
163 int MinorKey() {
164 // Encode the parameters in a unique 18 bit value.
165 return OpBits::encode(op_)
166 | ModeBits::encode(mode_)
167 | FlagBits::encode(flags_)
168 | SSE3Bits::encode(use_sse3_)
169 | ArgsInRegistersBits::encode(args_in_registers_)
170 | ArgsReversedBits::encode(args_reversed_)
171 | StaticTypeInfoBits::encode(
172 static_operands_type_.ThreeBitRepresentation())
173 | RuntimeTypeInfoBits::encode(runtime_operands_type_);
174 }
175
176 void Generate(MacroAssembler* masm);
177 void GenerateSmiCode(MacroAssembler* masm, Label* slow);
178 void GenerateLoadArguments(MacroAssembler* masm);
179 void GenerateReturn(MacroAssembler* masm);
180 void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure);
181 void GenerateRegisterArgsPush(MacroAssembler* masm);
182 void GenerateTypeTransition(MacroAssembler* masm);
183
184 bool IsOperationCommutative() {
185 return (op_ == Token::ADD) || (op_ == Token::MUL);
186 }
187
188 void SetArgsInRegisters() { args_in_registers_ = true; }
189 void SetArgsReversed() { args_reversed_ = true; }
190 bool HasSmiCodeInStub() { return (flags_ & NO_SMI_CODE_IN_STUB) == 0; }
191 bool HasArgsInRegisters() { return args_in_registers_; }
192 bool HasArgsReversed() { return args_reversed_; }
193
194 bool ShouldGenerateSmiCode() {
195 return HasSmiCodeInStub() &&
196 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
197 runtime_operands_type_ != BinaryOpIC::STRINGS;
198 }
199
200 bool ShouldGenerateFPCode() {
201 return runtime_operands_type_ != BinaryOpIC::STRINGS;
202 }
203
204 virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
205
206 virtual InlineCacheState GetICState() {
207 return BinaryOpIC::ToState(runtime_operands_type_);
208 }
209
210 friend class CodeGenerator;
211};
212
213
214class StringHelper : public AllStatic {
215 public:
216 // Generate code for copying characters using a simple loop. This should only
217 // be used in places where the number of characters is small and the
218 // additional setup and checking in GenerateCopyCharactersREP adds too much
219 // overhead. Copying of overlapping regions is not supported.
220 static void GenerateCopyCharacters(MacroAssembler* masm,
221 Register dest,
222 Register src,
223 Register count,
224 Register scratch,
225 bool ascii);
226
227 // Generate code for copying characters using the rep movs instruction.
228 // Copies ecx characters from esi to edi. Copying of overlapping regions is
229 // not supported.
230 static void GenerateCopyCharactersREP(MacroAssembler* masm,
231 Register dest, // Must be edi.
232 Register src, // Must be esi.
233 Register count, // Must be ecx.
234 Register scratch, // Neither of above.
235 bool ascii);
236
237 // Probe the symbol table for a two character string. If the string is
238 // not found by probing a jump to the label not_found is performed. This jump
239 // does not guarantee that the string is not in the symbol table. If the
240 // string is found the code falls through with the string in register eax.
241 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
242 Register c1,
243 Register c2,
244 Register scratch1,
245 Register scratch2,
246 Register scratch3,
247 Label* not_found);
248
249 // Generate string hash.
250 static void GenerateHashInit(MacroAssembler* masm,
251 Register hash,
252 Register character,
253 Register scratch);
254 static void GenerateHashAddCharacter(MacroAssembler* masm,
255 Register hash,
256 Register character,
257 Register scratch);
258 static void GenerateHashGetHash(MacroAssembler* masm,
259 Register hash,
260 Register scratch);
261
262 private:
263 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
264};
265
266
267// Flag that indicates how to generate code for the stub StringAddStub.
268enum StringAddFlags {
269 NO_STRING_ADD_FLAGS = 0,
270 NO_STRING_CHECK_IN_STUB = 1 << 0 // Omit string check in stub.
271};
272
273
274class StringAddStub: public CodeStub {
275 public:
276 explicit StringAddStub(StringAddFlags flags) {
277 string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
278 }
279
280 private:
281 Major MajorKey() { return StringAdd; }
282 int MinorKey() { return string_check_ ? 0 : 1; }
283
284 void Generate(MacroAssembler* masm);
285
286 // Should the stub check whether arguments are strings?
287 bool string_check_;
288};
289
290
291class SubStringStub: public CodeStub {
292 public:
293 SubStringStub() {}
294
295 private:
296 Major MajorKey() { return SubString; }
297 int MinorKey() { return 0; }
298
299 void Generate(MacroAssembler* masm);
300};
301
302
303class StringCompareStub: public CodeStub {
304 public:
305 explicit StringCompareStub() {
306 }
307
308 // Compare two flat ascii strings and returns result in eax after popping two
309 // arguments from the stack.
310 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
311 Register left,
312 Register right,
313 Register scratch1,
314 Register scratch2,
315 Register scratch3);
316
317 private:
318 Major MajorKey() { return StringCompare; }
319 int MinorKey() { return 0; }
320
321 void Generate(MacroAssembler* masm);
322};
323
324
325class NumberToStringStub: public CodeStub {
326 public:
327 NumberToStringStub() { }
328
329 // Generate code to do a lookup in the number string cache. If the number in
330 // the register object is found in the cache the generated code falls through
331 // with the result in the result register. The object and the result register
332 // can be the same. If the number is not found in the cache the code jumps to
333 // the label not_found with only the content of register object unchanged.
334 static void GenerateLookupNumberStringCache(MacroAssembler* masm,
335 Register object,
336 Register result,
337 Register scratch1,
338 Register scratch2,
339 bool object_is_smi,
340 Label* not_found);
341
342 private:
343 Major MajorKey() { return NumberToString; }
344 int MinorKey() { return 0; }
345
346 void Generate(MacroAssembler* masm);
347
348 const char* GetName() { return "NumberToStringStub"; }
349
350#ifdef DEBUG
351 void Print() {
352 PrintF("NumberToStringStub\n");
353 }
354#endif
355};
356
357
358} } // namespace v8::internal
359
360#endif // V8_IA32_CODE_STUBS_IA32_H_