blob: 246650af4548146ed691860e410bd7759afaab13 [file] [log] [blame]
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001// 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_X64_CODE_STUBS_X64_H_
29#define V8_X64_CODE_STUBS_X64_H_
30
31#include "ic-inl.h"
32#include "type-info.h"
33
34namespace v8 {
35namespace internal {
36
37
38// Compute a transcendental math function natively, or call the
39// TranscendentalCache runtime function.
40class TranscendentalCacheStub: public CodeStub {
41 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +010042 enum ArgumentType {
43 TAGGED = 0,
44 UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
45 };
46
47 explicit TranscendentalCacheStub(TranscendentalCache::Type type,
48 ArgumentType argument_type)
49 : type_(type), argument_type_(argument_type) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +010050 void Generate(MacroAssembler* masm);
51 private:
52 TranscendentalCache::Type type_;
Ben Murdoche0cee9b2011-05-25 10:26:03 +010053 ArgumentType argument_type_;
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();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010058 void GenerateOperation(MacroAssembler* masm);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010059};
60
61
62class ToBooleanStub: public CodeStub {
63 public:
64 ToBooleanStub() { }
65
66 void Generate(MacroAssembler* masm);
67
68 private:
69 Major MajorKey() { return ToBoolean; }
70 int MinorKey() { return 0; }
71};
72
73
74// Flag that indicates how to generate code for the stub GenericBinaryOpStub.
75enum GenericBinaryFlags {
76 NO_GENERIC_BINARY_FLAGS = 0,
77 NO_SMI_CODE_IN_STUB = 1 << 0 // Omit smi code in stub.
78};
79
80
81class GenericBinaryOpStub: public CodeStub {
82 public:
83 GenericBinaryOpStub(Token::Value op,
84 OverwriteMode mode,
85 GenericBinaryFlags flags,
86 TypeInfo operands_type = TypeInfo::Unknown())
87 : op_(op),
88 mode_(mode),
89 flags_(flags),
90 args_in_registers_(false),
91 args_reversed_(false),
92 static_operands_type_(operands_type),
93 runtime_operands_type_(BinaryOpIC::DEFAULT),
94 name_(NULL) {
95 ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
96 }
97
Steve Block9fac8402011-05-12 15:51:54 +010098 GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo runtime_operands_type)
Kristian Monsen80d68ea2010-09-08 11:05:35 +010099 : op_(OpBits::decode(key)),
100 mode_(ModeBits::decode(key)),
101 flags_(FlagBits::decode(key)),
102 args_in_registers_(ArgsInRegistersBits::decode(key)),
103 args_reversed_(ArgsReversedBits::decode(key)),
104 static_operands_type_(TypeInfo::ExpandedRepresentation(
105 StaticTypeInfoBits::decode(key))),
Steve Block9fac8402011-05-12 15:51:54 +0100106 runtime_operands_type_(runtime_operands_type),
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100107 name_(NULL) {
108 }
109
110 // Generate code to call the stub with the supplied arguments. This will add
111 // code at the call site to prepare arguments either in registers or on the
112 // stack together with the actual call.
113 void GenerateCall(MacroAssembler* masm, Register left, Register right);
114 void GenerateCall(MacroAssembler* masm, Register left, Smi* right);
115 void GenerateCall(MacroAssembler* masm, Smi* left, Register right);
116
117 bool ArgsInRegistersSupported() {
118 return (op_ == Token::ADD) || (op_ == Token::SUB)
119 || (op_ == Token::MUL) || (op_ == Token::DIV);
120 }
121
122 private:
123 Token::Value op_;
124 OverwriteMode mode_;
125 GenericBinaryFlags flags_;
126 bool args_in_registers_; // Arguments passed in registers not on the stack.
127 bool args_reversed_; // Left and right argument are swapped.
128
129 // Number type information of operands, determined by code generator.
130 TypeInfo static_operands_type_;
131
132 // Operand type information determined at runtime.
133 BinaryOpIC::TypeInfo runtime_operands_type_;
134
135 char* name_;
136
137 const char* GetName();
138
139#ifdef DEBUG
140 void Print() {
141 PrintF("GenericBinaryOpStub %d (op %s), "
Ben Murdoch086aeea2011-05-13 15:57:08 +0100142 "(mode %d, flags %d, registers %d, reversed %d, type_info %s)\n",
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100143 MinorKey(),
144 Token::String(op_),
145 static_cast<int>(mode_),
146 static_cast<int>(flags_),
147 static_cast<int>(args_in_registers_),
148 static_cast<int>(args_reversed_),
149 static_operands_type_.ToString());
150 }
151#endif
152
153 // Minor key encoding in 17 bits TTNNNFRAOOOOOOOMM.
154 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
155 class OpBits: public BitField<Token::Value, 2, 7> {};
156 class ArgsInRegistersBits: public BitField<bool, 9, 1> {};
157 class ArgsReversedBits: public BitField<bool, 10, 1> {};
158 class FlagBits: public BitField<GenericBinaryFlags, 11, 1> {};
159 class StaticTypeInfoBits: public BitField<int, 12, 3> {};
Ben Murdochb0fe1622011-05-05 13:52:32 +0100160 class RuntimeTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 15, 3> {};
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100161
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 | ArgsInRegistersBits::encode(args_in_registers_)
169 | ArgsReversedBits::encode(args_reversed_)
170 | StaticTypeInfoBits::encode(
171 static_operands_type_.ThreeBitRepresentation())
172 | RuntimeTypeInfoBits::encode(runtime_operands_type_);
173 }
174
175 void Generate(MacroAssembler* masm);
176 void GenerateSmiCode(MacroAssembler* masm, Label* slow);
177 void GenerateLoadArguments(MacroAssembler* masm);
178 void GenerateReturn(MacroAssembler* masm);
179 void GenerateRegisterArgsPush(MacroAssembler* masm);
180 void GenerateTypeTransition(MacroAssembler* masm);
181
182 bool IsOperationCommutative() {
183 return (op_ == Token::ADD) || (op_ == Token::MUL);
184 }
185
186 void SetArgsInRegisters() { args_in_registers_ = true; }
187 void SetArgsReversed() { args_reversed_ = true; }
188 bool HasSmiCodeInStub() { return (flags_ & NO_SMI_CODE_IN_STUB) == 0; }
189 bool HasArgsInRegisters() { return args_in_registers_; }
190 bool HasArgsReversed() { return args_reversed_; }
191
192 bool ShouldGenerateSmiCode() {
193 return HasSmiCodeInStub() &&
194 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
195 runtime_operands_type_ != BinaryOpIC::STRINGS;
196 }
197
198 bool ShouldGenerateFPCode() {
199 return runtime_operands_type_ != BinaryOpIC::STRINGS;
200 }
201
202 virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
203
204 virtual InlineCacheState GetICState() {
205 return BinaryOpIC::ToState(runtime_operands_type_);
206 }
207
208 friend class CodeGenerator;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100209 friend class LCodeGen;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100210};
211
Ben Murdoch086aeea2011-05-13 15:57:08 +0100212
213class TypeRecordingBinaryOpStub: public CodeStub {
214 public:
215 TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
216 : op_(op),
217 mode_(mode),
218 operands_type_(TRBinaryOpIC::UNINITIALIZED),
219 result_type_(TRBinaryOpIC::UNINITIALIZED),
220 name_(NULL) {
221 ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
222 }
223
224 TypeRecordingBinaryOpStub(
225 int key,
226 TRBinaryOpIC::TypeInfo operands_type,
227 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
228 : op_(OpBits::decode(key)),
229 mode_(ModeBits::decode(key)),
230 operands_type_(operands_type),
231 result_type_(result_type),
232 name_(NULL) { }
233
234 private:
235 enum SmiCodeGenerateHeapNumberResults {
236 ALLOW_HEAPNUMBER_RESULTS,
237 NO_HEAPNUMBER_RESULTS
238 };
239
240 Token::Value op_;
241 OverwriteMode mode_;
242
243 // Operand type information determined at runtime.
244 TRBinaryOpIC::TypeInfo operands_type_;
245 TRBinaryOpIC::TypeInfo result_type_;
246
247 char* name_;
248
249 const char* GetName();
250
251#ifdef DEBUG
252 void Print() {
253 PrintF("TypeRecordingBinaryOpStub %d (op %s), "
254 "(mode %d, runtime_type_info %s)\n",
255 MinorKey(),
256 Token::String(op_),
257 static_cast<int>(mode_),
258 TRBinaryOpIC::GetName(operands_type_));
259 }
260#endif
261
262 // Minor key encoding in 15 bits RRRTTTOOOOOOOMM.
263 class ModeBits: public BitField<OverwriteMode, 0, 2> {};
264 class OpBits: public BitField<Token::Value, 2, 7> {};
265 class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 9, 3> {};
266 class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 12, 3> {};
267
268 Major MajorKey() { return TypeRecordingBinaryOp; }
269 int MinorKey() {
270 return OpBits::encode(op_)
271 | ModeBits::encode(mode_)
272 | OperandTypeInfoBits::encode(operands_type_)
273 | ResultTypeInfoBits::encode(result_type_);
274 }
275
276 void Generate(MacroAssembler* masm);
277 void GenerateGeneric(MacroAssembler* masm);
278 void GenerateSmiCode(MacroAssembler* masm,
279 Label* slow,
280 SmiCodeGenerateHeapNumberResults heapnumber_results);
Steve Block1e0659c2011-05-24 12:43:12 +0100281 void GenerateFloatingPointCode(MacroAssembler* masm,
282 Label* allocation_failure,
283 Label* non_numeric_failure);
284 void GenerateStringAddCode(MacroAssembler* masm);
285 void GenerateCallRuntimeCode(MacroAssembler* masm);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100286 void GenerateLoadArguments(MacroAssembler* masm);
287 void GenerateReturn(MacroAssembler* masm);
288 void GenerateUninitializedStub(MacroAssembler* masm);
289 void GenerateSmiStub(MacroAssembler* masm);
290 void GenerateInt32Stub(MacroAssembler* masm);
291 void GenerateHeapNumberStub(MacroAssembler* masm);
Steve Block44f0eee2011-05-26 01:26:41 +0100292 void GenerateOddballStub(MacroAssembler* masm);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100293 void GenerateStringStub(MacroAssembler* masm);
294 void GenerateGenericStub(MacroAssembler* masm);
295
296 void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure);
297 void GenerateRegisterArgsPush(MacroAssembler* masm);
298 void GenerateTypeTransition(MacroAssembler* masm);
299 void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
300
301 virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
302
303 virtual InlineCacheState GetICState() {
304 return TRBinaryOpIC::ToState(operands_type_);
305 }
306
307 virtual void FinishCode(Code* code) {
308 code->set_type_recording_binary_op_type(operands_type_);
309 code->set_type_recording_binary_op_result_type(result_type_);
310 }
311
312 friend class CodeGenerator;
313};
314
315
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100316class StringHelper : public AllStatic {
317 public:
318 // Generate code for copying characters using a simple loop. This should only
319 // be used in places where the number of characters is small and the
320 // additional setup and checking in GenerateCopyCharactersREP adds too much
321 // overhead. Copying of overlapping regions is not supported.
322 static void GenerateCopyCharacters(MacroAssembler* masm,
323 Register dest,
324 Register src,
325 Register count,
326 bool ascii);
327
328 // Generate code for copying characters using the rep movs instruction.
329 // Copies rcx characters from rsi to rdi. Copying of overlapping regions is
330 // not supported.
331 static void GenerateCopyCharactersREP(MacroAssembler* masm,
332 Register dest, // Must be rdi.
333 Register src, // Must be rsi.
334 Register count, // Must be rcx.
335 bool ascii);
336
337
338 // Probe the symbol table for a two character string. If the string is
339 // not found by probing a jump to the label not_found is performed. This jump
340 // does not guarantee that the string is not in the symbol table. If the
341 // string is found the code falls through with the string in register rax.
342 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
343 Register c1,
344 Register c2,
345 Register scratch1,
346 Register scratch2,
347 Register scratch3,
348 Register scratch4,
349 Label* not_found);
350
351 // Generate string hash.
352 static void GenerateHashInit(MacroAssembler* masm,
353 Register hash,
354 Register character,
355 Register scratch);
356 static void GenerateHashAddCharacter(MacroAssembler* masm,
357 Register hash,
358 Register character,
359 Register scratch);
360 static void GenerateHashGetHash(MacroAssembler* masm,
361 Register hash,
362 Register scratch);
363
364 private:
365 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
366};
367
368
369// Flag that indicates how to generate code for the stub StringAddStub.
370enum StringAddFlags {
371 NO_STRING_ADD_FLAGS = 0,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100372 // Omit left string check in stub (left is definitely a string).
373 NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
374 // Omit right string check in stub (right is definitely a string).
375 NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
376 // Omit both string checks in stub.
377 NO_STRING_CHECK_IN_STUB =
378 NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100379};
380
381
382class StringAddStub: public CodeStub {
383 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100384 explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100385
386 private:
387 Major MajorKey() { return StringAdd; }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100388 int MinorKey() { return flags_; }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100389
390 void Generate(MacroAssembler* masm);
391
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100392 void GenerateConvertArgument(MacroAssembler* masm,
393 int stack_offset,
394 Register arg,
395 Register scratch1,
396 Register scratch2,
397 Register scratch3,
398 Label* slow);
399
400 const StringAddFlags flags_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100401};
402
403
404class SubStringStub: public CodeStub {
405 public:
406 SubStringStub() {}
407
408 private:
409 Major MajorKey() { return SubString; }
410 int MinorKey() { return 0; }
411
412 void Generate(MacroAssembler* masm);
413};
414
415
416class StringCompareStub: public CodeStub {
417 public:
418 explicit StringCompareStub() {}
419
420 // Compare two flat ascii strings and returns result in rax after popping two
421 // arguments from the stack.
422 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
423 Register left,
424 Register right,
425 Register scratch1,
426 Register scratch2,
427 Register scratch3,
428 Register scratch4);
429
430 private:
431 Major MajorKey() { return StringCompare; }
432 int MinorKey() { return 0; }
433
434 void Generate(MacroAssembler* masm);
435};
436
437
438class NumberToStringStub: public CodeStub {
439 public:
440 NumberToStringStub() { }
441
442 // Generate code to do a lookup in the number string cache. If the number in
443 // the register object is found in the cache the generated code falls through
444 // with the result in the result register. The object and the result register
445 // can be the same. If the number is not found in the cache the code jumps to
446 // the label not_found with only the content of register object unchanged.
447 static void GenerateLookupNumberStringCache(MacroAssembler* masm,
448 Register object,
449 Register result,
450 Register scratch1,
451 Register scratch2,
452 bool object_is_smi,
453 Label* not_found);
454
455 private:
456 static void GenerateConvertHashCodeToIndex(MacroAssembler* masm,
457 Register hash,
458 Register mask);
459
460 Major MajorKey() { return NumberToString; }
461 int MinorKey() { return 0; }
462
463 void Generate(MacroAssembler* masm);
464
465 const char* GetName() { return "NumberToStringStub"; }
466
467#ifdef DEBUG
468 void Print() {
469 PrintF("NumberToStringStub\n");
470 }
471#endif
472};
473
474
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100475} } // namespace v8::internal
476
477#endif // V8_X64_CODE_STUBS_X64_H_