| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 | 54 |
| 55 // Nested stubs are not allowed for leafs. | 55 // Nested stubs are not allowed for leafs. |
| 56 AllowStubCallsScope allow_scope(masm, AllowsStubCalls()); | 56 AllowStubCallsScope allow_scope(masm, AllowsStubCalls()); |
| 57 | 57 |
| 58 // Generate the code for the stub. | 58 // Generate the code for the stub. |
| 59 masm->set_generating_stub(true); | 59 masm->set_generating_stub(true); |
| 60 Generate(masm); | 60 Generate(masm); |
| 61 } | 61 } |
| 62 | 62 |
| 63 | 63 |
| 64 SmartPointer<const char> CodeStub::GetName() { |
| 65 char buffer[100]; |
| 66 NoAllocationStringAllocator allocator(buffer, |
| 67 static_cast<unsigned>(sizeof(buffer))); |
| 68 StringStream stream(&allocator); |
| 69 PrintName(&stream); |
| 70 return stream.ToCString(); |
| 71 } |
| 72 |
| 73 |
| 64 void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) { | 74 void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) { |
| 65 code->set_major_key(MajorKey()); | 75 code->set_major_key(MajorKey()); |
| 66 | 76 |
| 67 Isolate* isolate = masm->isolate(); | 77 Isolate* isolate = masm->isolate(); |
| 68 PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, GetName())); | 78 SmartPointer<const char> name = GetName(); |
| 69 GDBJIT(AddCode(GDBJITInterface::STUB, GetName(), code)); | 79 PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, *name)); |
| 80 GDBJIT(AddCode(GDBJITInterface::STUB, *name, code)); |
| 70 Counters* counters = isolate->counters(); | 81 Counters* counters = isolate->counters(); |
| 71 counters->total_stubs_code_size()->Increment(code->instruction_size()); | 82 counters->total_stubs_code_size()->Increment(code->instruction_size()); |
| 72 | 83 |
| 73 #ifdef ENABLE_DISASSEMBLER | 84 #ifdef ENABLE_DISASSEMBLER |
| 74 if (FLAG_print_code_stubs) { | 85 if (FLAG_print_code_stubs) { |
| 75 #ifdef DEBUG | 86 code->Disassemble(*name); |
| 76 Print(); | |
| 77 #endif | |
| 78 code->Disassemble(GetName()); | |
| 79 PrintF("\n"); | 87 PrintF("\n"); |
| 80 } | 88 } |
| 81 #endif | 89 #endif |
| 82 } | 90 } |
| 83 | 91 |
| 84 | 92 |
| 85 int CodeStub::GetCodeKind() { | 93 int CodeStub::GetCodeKind() { |
| 86 return Code::STUB; | 94 return Code::STUB; |
| 87 } | 95 } |
| 88 | 96 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 break; | 218 break; |
| 211 case CompareIC::OBJECTS: | 219 case CompareIC::OBJECTS: |
| 212 GenerateObjects(masm); | 220 GenerateObjects(masm); |
| 213 break; | 221 break; |
| 214 default: | 222 default: |
| 215 UNREACHABLE(); | 223 UNREACHABLE(); |
| 216 } | 224 } |
| 217 } | 225 } |
| 218 | 226 |
| 219 | 227 |
| 220 const char* InstanceofStub::GetName() { | 228 void InstanceofStub::PrintName(StringStream* stream) { |
| 221 if (name_ != NULL) return name_; | |
| 222 const int kMaxNameLength = 100; | |
| 223 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( | |
| 224 kMaxNameLength); | |
| 225 if (name_ == NULL) return "OOM"; | |
| 226 | |
| 227 const char* args = ""; | 229 const char* args = ""; |
| 228 if (HasArgsInRegisters()) { | 230 if (HasArgsInRegisters()) { |
| 229 args = "_REGS"; | 231 args = "_REGS"; |
| 230 } | 232 } |
| 231 | 233 |
| 232 const char* inline_check = ""; | 234 const char* inline_check = ""; |
| 233 if (HasCallSiteInlineCheck()) { | 235 if (HasCallSiteInlineCheck()) { |
| 234 inline_check = "_INLINE"; | 236 inline_check = "_INLINE"; |
| 235 } | 237 } |
| 236 | 238 |
| 237 const char* return_true_false_object = ""; | 239 const char* return_true_false_object = ""; |
| 238 if (ReturnTrueFalseObject()) { | 240 if (ReturnTrueFalseObject()) { |
| 239 return_true_false_object = "_TRUEFALSE"; | 241 return_true_false_object = "_TRUEFALSE"; |
| 240 } | 242 } |
| 241 | 243 |
| 242 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 244 stream->Add("InstanceofStub%s%s%s", |
| 243 "InstanceofStub%s%s%s", | 245 args, |
| 244 args, | 246 inline_check, |
| 245 inline_check, | 247 return_true_false_object); |
| 246 return_true_false_object); | |
| 247 return name_; | |
| 248 } | 248 } |
| 249 | 249 |
| 250 | 250 |
| 251 void KeyedLoadElementStub::Generate(MacroAssembler* masm) { | 251 void KeyedLoadElementStub::Generate(MacroAssembler* masm) { |
| 252 switch (elements_kind_) { | 252 switch (elements_kind_) { |
| 253 case JSObject::FAST_ELEMENTS: | 253 case JSObject::FAST_ELEMENTS: |
| 254 KeyedLoadStubCompiler::GenerateLoadFastElement(masm); | 254 KeyedLoadStubCompiler::GenerateLoadFastElement(masm); |
| 255 break; | 255 break; |
| 256 case JSObject::FAST_DOUBLE_ELEMENTS: | 256 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 257 UNIMPLEMENTED(); | 257 KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(masm); |
| 258 break; | 258 break; |
| 259 case JSObject::EXTERNAL_BYTE_ELEMENTS: | 259 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 260 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 260 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 261 case JSObject::EXTERNAL_SHORT_ELEMENTS: | 261 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 262 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 262 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 263 case JSObject::EXTERNAL_INT_ELEMENTS: | 263 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 264 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: | 264 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 265 case JSObject::EXTERNAL_FLOAT_ELEMENTS: | 265 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 266 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: | 266 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 267 case JSObject::EXTERNAL_PIXEL_ELEMENTS: | 267 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 268 KeyedLoadStubCompiler::GenerateLoadExternalArray(masm, elements_kind_); | 268 KeyedLoadStubCompiler::GenerateLoadExternalArray(masm, elements_kind_); |
| 269 break; | 269 break; |
| 270 case JSObject::DICTIONARY_ELEMENTS: | 270 case JSObject::DICTIONARY_ELEMENTS: |
| 271 KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm); | 271 KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm); |
| 272 break; | 272 break; |
| 273 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: | 273 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 274 UNREACHABLE(); | 274 UNREACHABLE(); |
| 275 break; | 275 break; |
| 276 } | 276 } |
| 277 } | 277 } |
| 278 | 278 |
| 279 | 279 |
| 280 void KeyedStoreElementStub::Generate(MacroAssembler* masm) { | 280 void KeyedStoreElementStub::Generate(MacroAssembler* masm) { |
| 281 switch (elements_kind_) { | 281 switch (elements_kind_) { |
| 282 case JSObject::FAST_ELEMENTS: | 282 case JSObject::FAST_ELEMENTS: |
| 283 KeyedStoreStubCompiler::GenerateStoreFastElement(masm, is_js_array_); | 283 KeyedStoreStubCompiler::GenerateStoreFastElement(masm, is_js_array_); |
| 284 break; | 284 break; |
| 285 case JSObject::FAST_DOUBLE_ELEMENTS: | 285 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 286 UNIMPLEMENTED(); | 286 KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm, |
| 287 is_js_array_); |
| 287 break; | 288 break; |
| 288 case JSObject::EXTERNAL_BYTE_ELEMENTS: | 289 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 289 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 290 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 290 case JSObject::EXTERNAL_SHORT_ELEMENTS: | 291 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 291 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 292 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 292 case JSObject::EXTERNAL_INT_ELEMENTS: | 293 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 293 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: | 294 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 294 case JSObject::EXTERNAL_FLOAT_ELEMENTS: | 295 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 295 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: | 296 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 296 case JSObject::EXTERNAL_PIXEL_ELEMENTS: | 297 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 297 KeyedStoreStubCompiler::GenerateStoreExternalArray(masm, elements_kind_); | 298 KeyedStoreStubCompiler::GenerateStoreExternalArray(masm, elements_kind_); |
| 298 break; | 299 break; |
| 299 case JSObject::DICTIONARY_ELEMENTS: | 300 case JSObject::DICTIONARY_ELEMENTS: |
| 300 KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm); | 301 KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm); |
| 301 break; | 302 break; |
| 302 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: | 303 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 303 UNREACHABLE(); | 304 UNREACHABLE(); |
| 304 break; | 305 break; |
| 305 } | 306 } |
| 306 } | 307 } |
| 307 | 308 |
| 308 | 309 |
| 310 void ArgumentsAccessStub::PrintName(StringStream* stream) { |
| 311 const char* type_name = NULL; // Make g++ happy. |
| 312 switch (type_) { |
| 313 case READ_ELEMENT: type_name = "ReadElement"; break; |
| 314 case NEW_NON_STRICT_FAST: type_name = "NewNonStrictFast"; break; |
| 315 case NEW_NON_STRICT_SLOW: type_name = "NewNonStrictSlow"; break; |
| 316 case NEW_STRICT: type_name = "NewStrict"; break; |
| 317 } |
| 318 stream->Add("ArgumentsAccessStub_%s", type_name); |
| 319 } |
| 320 |
| 321 |
| 322 void CallFunctionStub::PrintName(StringStream* stream) { |
| 323 const char* in_loop_name = NULL; // Make g++ happy. |
| 324 switch (in_loop_) { |
| 325 case NOT_IN_LOOP: in_loop_name = ""; break; |
| 326 case IN_LOOP: in_loop_name = "_InLoop"; break; |
| 327 } |
| 328 const char* flags_name = NULL; // Make g++ happy. |
| 329 switch (flags_) { |
| 330 case NO_CALL_FUNCTION_FLAGS: flags_name = ""; break; |
| 331 case RECEIVER_MIGHT_BE_IMPLICIT: flags_name = "_Implicit"; break; |
| 332 } |
| 333 stream->Add("CallFunctionStub_Args%d%s%s", argc_, in_loop_name, flags_name); |
| 334 } |
| 335 |
| 336 |
| 337 void ToBooleanStub::PrintName(StringStream* stream) { |
| 338 stream->Add("ToBooleanStub_"); |
| 339 types_.Print(stream); |
| 340 } |
| 341 |
| 342 |
| 343 void ToBooleanStub::Types::Print(StringStream* stream) const { |
| 344 if (IsEmpty()) stream->Add("None"); |
| 345 if (Contains(UNDEFINED)) stream->Add("Undefined"); |
| 346 if (Contains(BOOLEAN)) stream->Add("Bool"); |
| 347 if (Contains(SMI)) stream->Add("Smi"); |
| 348 if (Contains(NULL_TYPE)) stream->Add("Null"); |
| 349 if (Contains(SPEC_OBJECT)) stream->Add("SpecObject"); |
| 350 if (Contains(STRING)) stream->Add("String"); |
| 351 if (Contains(HEAP_NUMBER)) stream->Add("HeapNumber"); |
| 352 if (Contains(INTERNAL_OBJECT)) stream->Add("InternalObject"); |
| 353 } |
| 354 |
| 355 |
| 356 void ToBooleanStub::Types::TraceTransition(Types to) const { |
| 357 if (!FLAG_trace_ic) return; |
| 358 char buffer[100]; |
| 359 NoAllocationStringAllocator allocator(buffer, |
| 360 static_cast<unsigned>(sizeof(buffer))); |
| 361 StringStream stream(&allocator); |
| 362 stream.Add("[ToBooleanIC ("); |
| 363 Print(&stream); |
| 364 stream.Add("->"); |
| 365 to.Print(&stream); |
| 366 stream.Add(")]\n"); |
| 367 stream.OutputToStdOut(); |
| 368 } |
| 369 |
| 370 |
| 371 bool ToBooleanStub::Types::Record(Handle<Object> object) { |
| 372 if (object->IsUndefined()) { |
| 373 Add(UNDEFINED); |
| 374 return false; |
| 375 } else if (object->IsBoolean()) { |
| 376 Add(BOOLEAN); |
| 377 return object->IsTrue(); |
| 378 } else if (object->IsNull()) { |
| 379 Add(NULL_TYPE); |
| 380 return false; |
| 381 } else if (object->IsSmi()) { |
| 382 Add(SMI); |
| 383 return Smi::cast(*object)->value() != 0; |
| 384 } else if (object->IsSpecObject()) { |
| 385 Add(SPEC_OBJECT); |
| 386 return !object->IsUndetectableObject(); |
| 387 } else if (object->IsString()) { |
| 388 Add(STRING); |
| 389 return !object->IsUndetectableObject() && |
| 390 String::cast(*object)->length() != 0; |
| 391 } else if (object->IsHeapNumber()) { |
| 392 Add(HEAP_NUMBER); |
| 393 double value = HeapNumber::cast(*object)->value(); |
| 394 return !object->IsUndetectableObject() && value != 0 && !isnan(value); |
| 395 } else { |
| 396 Add(INTERNAL_OBJECT); |
| 397 return !object->IsUndetectableObject(); |
| 398 } |
| 399 } |
| 400 |
| 401 |
| 402 bool ToBooleanStub::Types::NeedsMap() const { |
| 403 return Contains(ToBooleanStub::SPEC_OBJECT) |
| 404 || Contains(ToBooleanStub::STRING) |
| 405 || Contains(ToBooleanStub::HEAP_NUMBER) |
| 406 || Contains(ToBooleanStub::INTERNAL_OBJECT); |
| 407 } |
| 408 |
| 409 |
| 309 } } // namespace v8::internal | 410 } } // namespace v8::internal |
| OLD | NEW |