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