1 // Copyright 2011 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_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 34 namespace v8 { 35 namespace internal { 36 37 38 // Compute a transcendental math function natively, or call the 39 // TranscendentalCache runtime function. 40 class TranscendentalCacheStub: public CodeStub { 41 public: 42 enum ArgumentType { 43 TAGGED = 0, 44 UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits 45 }; 46 TranscendentalCacheStub(TranscendentalCache::Type type,ArgumentType argument_type)47 explicit TranscendentalCacheStub(TranscendentalCache::Type type, 48 ArgumentType argument_type) 49 : type_(type), argument_type_(argument_type) {} 50 void Generate(MacroAssembler* masm); 51 private: 52 TranscendentalCache::Type type_; 53 ArgumentType argument_type_; 54 MajorKey()55 Major MajorKey() { return TranscendentalCache; } MinorKey()56 int MinorKey() { return type_ | argument_type_; } 57 Runtime::FunctionId RuntimeFunction(); 58 void GenerateOperation(MacroAssembler* masm); 59 }; 60 61 62 class ToBooleanStub: public CodeStub { 63 public: ToBooleanStub()64 ToBooleanStub() { } 65 66 void Generate(MacroAssembler* masm); 67 68 private: MajorKey()69 Major MajorKey() { return ToBoolean; } MinorKey()70 int MinorKey() { return 0; } 71 }; 72 73 74 class TypeRecordingBinaryOpStub: public CodeStub { 75 public: TypeRecordingBinaryOpStub(Token::Value op,OverwriteMode mode)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 ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); 83 } 84 85 TypeRecordingBinaryOpStub( 86 int key, 87 TRBinaryOpIC::TypeInfo operands_type, 88 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED) op_(OpBits::decode (key))89 : op_(OpBits::decode(key)), 90 mode_(ModeBits::decode(key)), 91 operands_type_(operands_type), 92 result_type_(result_type), 93 name_(NULL) { } 94 95 private: 96 enum SmiCodeGenerateHeapNumberResults { 97 ALLOW_HEAPNUMBER_RESULTS, 98 NO_HEAPNUMBER_RESULTS 99 }; 100 101 Token::Value op_; 102 OverwriteMode mode_; 103 104 // Operand type information determined at runtime. 105 TRBinaryOpIC::TypeInfo operands_type_; 106 TRBinaryOpIC::TypeInfo result_type_; 107 108 char* name_; 109 110 const char* GetName(); 111 112 #ifdef DEBUG Print()113 void Print() { 114 PrintF("TypeRecordingBinaryOpStub %d (op %s), " 115 "(mode %d, runtime_type_info %s)\n", 116 MinorKey(), 117 Token::String(op_), 118 static_cast<int>(mode_), 119 TRBinaryOpIC::GetName(operands_type_)); 120 } 121 #endif 122 123 // Minor key encoding in 15 bits RRRTTTOOOOOOOMM. 124 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; 125 class OpBits: public BitField<Token::Value, 2, 7> {}; 126 class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 9, 3> {}; 127 class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 12, 3> {}; 128 MajorKey()129 Major MajorKey() { return TypeRecordingBinaryOp; } MinorKey()130 int MinorKey() { 131 return OpBits::encode(op_) 132 | ModeBits::encode(mode_) 133 | OperandTypeInfoBits::encode(operands_type_) 134 | ResultTypeInfoBits::encode(result_type_); 135 } 136 137 void Generate(MacroAssembler* masm); 138 void GenerateGeneric(MacroAssembler* masm); 139 void GenerateSmiCode(MacroAssembler* masm, 140 Label* slow, 141 SmiCodeGenerateHeapNumberResults heapnumber_results); 142 void GenerateFloatingPointCode(MacroAssembler* masm, 143 Label* allocation_failure, 144 Label* non_numeric_failure); 145 void GenerateStringAddCode(MacroAssembler* masm); 146 void GenerateCallRuntimeCode(MacroAssembler* masm); 147 void GenerateLoadArguments(MacroAssembler* masm); 148 void GenerateReturn(MacroAssembler* masm); 149 void GenerateUninitializedStub(MacroAssembler* masm); 150 void GenerateSmiStub(MacroAssembler* masm); 151 void GenerateInt32Stub(MacroAssembler* masm); 152 void GenerateHeapNumberStub(MacroAssembler* masm); 153 void GenerateOddballStub(MacroAssembler* masm); 154 void GenerateStringStub(MacroAssembler* masm); 155 void GenerateGenericStub(MacroAssembler* masm); 156 157 void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure); 158 void GenerateRegisterArgsPush(MacroAssembler* masm); 159 void GenerateTypeTransition(MacroAssembler* masm); 160 void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm); 161 GetCodeKind()162 virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; } 163 GetICState()164 virtual InlineCacheState GetICState() { 165 return TRBinaryOpIC::ToState(operands_type_); 166 } 167 FinishCode(Code * code)168 virtual void FinishCode(Code* code) { 169 code->set_type_recording_binary_op_type(operands_type_); 170 code->set_type_recording_binary_op_result_type(result_type_); 171 } 172 173 friend class CodeGenerator; 174 }; 175 176 177 class StringHelper : public AllStatic { 178 public: 179 // Generate code for copying characters using a simple loop. This should only 180 // be used in places where the number of characters is small and the 181 // additional setup and checking in GenerateCopyCharactersREP adds too much 182 // overhead. Copying of overlapping regions is not supported. 183 static void GenerateCopyCharacters(MacroAssembler* masm, 184 Register dest, 185 Register src, 186 Register count, 187 bool ascii); 188 189 // Generate code for copying characters using the rep movs instruction. 190 // Copies rcx characters from rsi to rdi. Copying of overlapping regions is 191 // not supported. 192 static void GenerateCopyCharactersREP(MacroAssembler* masm, 193 Register dest, // Must be rdi. 194 Register src, // Must be rsi. 195 Register count, // Must be rcx. 196 bool ascii); 197 198 199 // Probe the symbol table for a two character string. If the string is 200 // not found by probing a jump to the label not_found is performed. This jump 201 // does not guarantee that the string is not in the symbol table. If the 202 // string is found the code falls through with the string in register rax. 203 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, 204 Register c1, 205 Register c2, 206 Register scratch1, 207 Register scratch2, 208 Register scratch3, 209 Register scratch4, 210 Label* not_found); 211 212 // Generate string hash. 213 static void GenerateHashInit(MacroAssembler* masm, 214 Register hash, 215 Register character, 216 Register scratch); 217 static void GenerateHashAddCharacter(MacroAssembler* masm, 218 Register hash, 219 Register character, 220 Register scratch); 221 static void GenerateHashGetHash(MacroAssembler* masm, 222 Register hash, 223 Register scratch); 224 225 private: 226 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); 227 }; 228 229 230 // Flag that indicates how to generate code for the stub StringAddStub. 231 enum StringAddFlags { 232 NO_STRING_ADD_FLAGS = 0, 233 // Omit left string check in stub (left is definitely a string). 234 NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0, 235 // Omit right string check in stub (right is definitely a string). 236 NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1, 237 // Omit both string checks in stub. 238 NO_STRING_CHECK_IN_STUB = 239 NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB 240 }; 241 242 243 class StringAddStub: public CodeStub { 244 public: StringAddStub(StringAddFlags flags)245 explicit StringAddStub(StringAddFlags flags) : flags_(flags) {} 246 247 private: MajorKey()248 Major MajorKey() { return StringAdd; } MinorKey()249 int MinorKey() { return flags_; } 250 251 void Generate(MacroAssembler* masm); 252 253 void GenerateConvertArgument(MacroAssembler* masm, 254 int stack_offset, 255 Register arg, 256 Register scratch1, 257 Register scratch2, 258 Register scratch3, 259 Label* slow); 260 261 const StringAddFlags flags_; 262 }; 263 264 265 class SubStringStub: public CodeStub { 266 public: SubStringStub()267 SubStringStub() {} 268 269 private: MajorKey()270 Major MajorKey() { return SubString; } MinorKey()271 int MinorKey() { return 0; } 272 273 void Generate(MacroAssembler* masm); 274 }; 275 276 277 class StringCompareStub: public CodeStub { 278 public: StringCompareStub()279 explicit StringCompareStub() {} 280 281 // Compare two flat ascii strings and returns result in rax after popping two 282 // arguments from the stack. 283 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 284 Register left, 285 Register right, 286 Register scratch1, 287 Register scratch2, 288 Register scratch3, 289 Register scratch4); 290 291 private: MajorKey()292 Major MajorKey() { return StringCompare; } MinorKey()293 int MinorKey() { return 0; } 294 295 void Generate(MacroAssembler* masm); 296 }; 297 298 299 class NumberToStringStub: public CodeStub { 300 public: NumberToStringStub()301 NumberToStringStub() { } 302 303 // Generate code to do a lookup in the number string cache. If the number in 304 // the register object is found in the cache the generated code falls through 305 // with the result in the result register. The object and the result register 306 // can be the same. If the number is not found in the cache the code jumps to 307 // the label not_found with only the content of register object unchanged. 308 static void GenerateLookupNumberStringCache(MacroAssembler* masm, 309 Register object, 310 Register result, 311 Register scratch1, 312 Register scratch2, 313 bool object_is_smi, 314 Label* not_found); 315 316 private: 317 static void GenerateConvertHashCodeToIndex(MacroAssembler* masm, 318 Register hash, 319 Register mask); 320 MajorKey()321 Major MajorKey() { return NumberToString; } MinorKey()322 int MinorKey() { return 0; } 323 324 void Generate(MacroAssembler* masm); 325 GetName()326 const char* GetName() { return "NumberToStringStub"; } 327 328 #ifdef DEBUG Print()329 void Print() { 330 PrintF("NumberToStringStub\n"); 331 } 332 #endif 333 }; 334 335 336 } } // namespace v8::internal 337 338 #endif // V8_X64_CODE_STUBS_X64_H_ 339