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