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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 LoadStubCompiler compiler(isolate_); | 154 LoadStubCompiler compiler(isolate_); |
155 Handle<Code> code = | 155 Handle<Code> code = |
156 compiler.CompileLoadField(receiver, holder, field_index, name); | 156 compiler.CompileLoadField(receiver, holder, field_index, name); |
157 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 157 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
158 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 158 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
159 JSObject::UpdateMapCodeCache(receiver, name, code); | 159 JSObject::UpdateMapCodeCache(receiver, name, code); |
160 return code; | 160 return code; |
161 } | 161 } |
162 | 162 |
163 | 163 |
164 Handle<Code> LoadStubCompiler::CompileLoadCallback( | |
165 Handle<String> name, | |
166 Handle<JSObject> object, | |
167 Handle<JSObject> holder, | |
168 Handle<AccessorInfo> callback) { | |
169 CALL_HEAP_FUNCTION(isolate(), | |
170 (set_failure(NULL), | |
171 CompileLoadCallback(*name, *object, *holder, *callback)), | |
172 Code); | |
173 } | |
174 | |
175 | |
176 Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name, | 164 Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name, |
177 Handle<JSObject> receiver, | 165 Handle<JSObject> receiver, |
178 Handle<JSObject> holder, | 166 Handle<JSObject> holder, |
179 Handle<AccessorInfo> callback) { | 167 Handle<AccessorInfo> callback) { |
180 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); | 168 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); |
181 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); | 169 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
182 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS); | 170 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS); |
183 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); | 171 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
184 if (probe->IsCode()) return Handle<Code>::cast(probe); | 172 if (probe->IsCode()) return Handle<Code>::cast(probe); |
185 | 173 |
(...skipping 20 matching lines...) Expand all Loading... |
206 LoadStubCompiler compiler(isolate_); | 194 LoadStubCompiler compiler(isolate_); |
207 Handle<Code> code = | 195 Handle<Code> code = |
208 compiler.CompileLoadConstant(receiver, holder, value, name); | 196 compiler.CompileLoadConstant(receiver, holder, value, name); |
209 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 197 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
210 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 198 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
211 JSObject::UpdateMapCodeCache(receiver, name, code); | 199 JSObject::UpdateMapCodeCache(receiver, name, code); |
212 return code; | 200 return code; |
213 } | 201 } |
214 | 202 |
215 | 203 |
216 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, | |
217 Handle<JSObject> holder, | |
218 Handle<String> name) { | |
219 CALL_HEAP_FUNCTION(isolate(), | |
220 (set_failure(NULL), | |
221 CompileLoadInterceptor(*object, *holder, *name)), | |
222 Code); | |
223 } | |
224 | |
225 | |
226 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name, | 204 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name, |
227 Handle<JSObject> receiver, | 205 Handle<JSObject> receiver, |
228 Handle<JSObject> holder) { | 206 Handle<JSObject> holder) { |
229 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); | 207 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
230 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR); | 208 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR); |
231 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); | 209 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
232 if (probe->IsCode()) return Handle<Code>::cast(probe); | 210 if (probe->IsCode()) return Handle<Code>::cast(probe); |
233 | 211 |
234 LoadStubCompiler compiler(isolate_); | 212 LoadStubCompiler compiler(isolate_); |
235 Handle<Code> code = | 213 Handle<Code> code = |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 KeyedLoadStubCompiler compiler(isolate_); | 276 KeyedLoadStubCompiler compiler(isolate_); |
299 Handle<Code> code = | 277 Handle<Code> code = |
300 compiler.CompileLoadConstant(name, receiver, holder, value); | 278 compiler.CompileLoadConstant(name, receiver, holder, value); |
301 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 279 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
302 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); | 280 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
303 JSObject::UpdateMapCodeCache(receiver, name, code); | 281 JSObject::UpdateMapCodeCache(receiver, name, code); |
304 return code; | 282 return code; |
305 } | 283 } |
306 | 284 |
307 | 285 |
308 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( | |
309 Handle<JSObject> object, | |
310 Handle<JSObject> holder, | |
311 Handle<String> name) { | |
312 CALL_HEAP_FUNCTION(isolate(), | |
313 (set_failure(NULL), | |
314 CompileLoadInterceptor(*object, *holder, *name)), | |
315 Code); | |
316 } | |
317 | |
318 | |
319 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name, | 286 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name, |
320 Handle<JSObject> receiver, | 287 Handle<JSObject> receiver, |
321 Handle<JSObject> holder) { | 288 Handle<JSObject> holder) { |
322 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); | 289 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
323 Code::Flags flags = | 290 Code::Flags flags = |
324 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR); | 291 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR); |
325 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); | 292 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
326 if (probe->IsCode()) return Handle<Code>::cast(probe); | 293 if (probe->IsCode()) return Handle<Code>::cast(probe); |
327 | 294 |
328 KeyedLoadStubCompiler compiler(isolate_); | 295 KeyedLoadStubCompiler compiler(isolate_); |
329 Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name); | 296 Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name); |
330 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 297 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
331 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); | 298 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
332 JSObject::UpdateMapCodeCache(receiver, name, code); | 299 JSObject::UpdateMapCodeCache(receiver, name, code); |
333 return code; | 300 return code; |
334 } | 301 } |
335 | 302 |
336 | 303 |
337 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( | |
338 Handle<String> name, | |
339 Handle<JSObject> object, | |
340 Handle<JSObject> holder, | |
341 Handle<AccessorInfo> callback) { | |
342 CALL_HEAP_FUNCTION(isolate(), | |
343 (set_failure(NULL), | |
344 CompileLoadCallback(*name, *object, *holder, *callback)), | |
345 Code); | |
346 } | |
347 | |
348 | |
349 Handle<Code> StubCache::ComputeKeyedLoadCallback( | 304 Handle<Code> StubCache::ComputeKeyedLoadCallback( |
350 Handle<String> name, | 305 Handle<String> name, |
351 Handle<JSObject> receiver, | 306 Handle<JSObject> receiver, |
352 Handle<JSObject> holder, | 307 Handle<JSObject> holder, |
353 Handle<AccessorInfo> callback) { | 308 Handle<AccessorInfo> callback) { |
354 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); | 309 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP); |
355 Code::Flags flags = | 310 Code::Flags flags = |
356 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 311 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
357 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); | 312 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags)); |
358 if (probe->IsCode()) return Handle<Code>::cast(probe); | 313 if (probe->IsCode()) return Handle<Code>::cast(probe); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); | 525 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); |
571 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); | 526 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); |
572 JSObject::UpdateMapCodeCache(receiver, name, code); | 527 JSObject::UpdateMapCodeCache(receiver, name, code); |
573 return code; | 528 return code; |
574 } | 529 } |
575 | 530 |
576 | 531 |
577 #define CALL_LOGGER_TAG(kind, type) \ | 532 #define CALL_LOGGER_TAG(kind, type) \ |
578 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | 533 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
579 | 534 |
580 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, | |
581 Handle<JSObject> holder, | |
582 Handle<JSFunction> function, | |
583 Handle<String> name, | |
584 CheckType check) { | |
585 CALL_HEAP_FUNCTION( | |
586 isolate(), | |
587 (set_failure(NULL), | |
588 CompileCallConstant(*object, *holder, *function, *name, check)), | |
589 Code); | |
590 } | |
591 | |
592 | |
593 Handle<Code> StubCache::ComputeCallConstant(int argc, | 535 Handle<Code> StubCache::ComputeCallConstant(int argc, |
594 Code::Kind kind, | 536 Code::Kind kind, |
595 Code::ExtraICState extra_state, | 537 Code::ExtraICState extra_state, |
596 Handle<String> name, | 538 Handle<String> name, |
597 Handle<Object> object, | 539 Handle<Object> object, |
598 Handle<JSObject> holder, | 540 Handle<JSObject> holder, |
599 Handle<JSFunction> function) { | 541 Handle<JSFunction> function) { |
600 // Compute the check type and the map. | 542 // Compute the check type and the map. |
601 InlineCacheHolderFlag cache_holder = | 543 InlineCacheHolderFlag cache_holder = |
602 IC::GetCodeCacheForObject(*object, *holder); | 544 IC::GetCodeCacheForObject(*object, *holder); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 holder, index, name); | 604 holder, index, name); |
663 ASSERT_EQ(flags, code->flags()); | 605 ASSERT_EQ(flags, code->flags()); |
664 PROFILE(isolate_, | 606 PROFILE(isolate_, |
665 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 607 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
666 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 608 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
667 JSObject::UpdateMapCodeCache(map_holder, name, code); | 609 JSObject::UpdateMapCodeCache(map_holder, name, code); |
668 return code; | 610 return code; |
669 } | 611 } |
670 | 612 |
671 | 613 |
672 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | |
673 Handle<JSObject> holder, | |
674 Handle<String> name) { | |
675 CALL_HEAP_FUNCTION( | |
676 isolate(), | |
677 (set_failure(NULL), CompileCallInterceptor(*object, *holder, *name)), | |
678 Code); | |
679 } | |
680 | |
681 | |
682 Handle<Code> StubCache::ComputeCallInterceptor(int argc, | 614 Handle<Code> StubCache::ComputeCallInterceptor(int argc, |
683 Code::Kind kind, | 615 Code::Kind kind, |
684 Code::ExtraICState extra_state, | 616 Code::ExtraICState extra_state, |
685 Handle<String> name, | 617 Handle<String> name, |
686 Handle<Object> object, | 618 Handle<Object> object, |
687 Handle<JSObject> holder) { | 619 Handle<JSObject> holder) { |
688 // Compute the check type and the map. | 620 // Compute the check type and the map. |
689 InlineCacheHolderFlag cache_holder = | 621 InlineCacheHolderFlag cache_holder = |
690 IC::GetCodeCacheForObject(*object, *holder); | 622 IC::GetCodeCacheForObject(*object, *holder); |
691 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder)); | 623 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder)); |
(...skipping 17 matching lines...) Expand all Loading... |
709 holder, name); | 641 holder, name); |
710 ASSERT_EQ(flags, code->flags()); | 642 ASSERT_EQ(flags, code->flags()); |
711 PROFILE(isolate(), | 643 PROFILE(isolate(), |
712 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 644 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
713 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 645 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
714 JSObject::UpdateMapCodeCache(map_holder, name, code); | 646 JSObject::UpdateMapCodeCache(map_holder, name, code); |
715 return code; | 647 return code; |
716 } | 648 } |
717 | 649 |
718 | 650 |
719 Handle<Code> CallStubCompiler::CompileCallGlobal( | |
720 Handle<JSObject> object, | |
721 Handle<GlobalObject> holder, | |
722 Handle<JSGlobalPropertyCell> cell, | |
723 Handle<JSFunction> function, | |
724 Handle<String> name) { | |
725 CALL_HEAP_FUNCTION( | |
726 isolate(), | |
727 (set_failure(NULL), | |
728 CompileCallGlobal(*object, *holder, *cell, *function, *name)), | |
729 Code); | |
730 } | |
731 | |
732 | |
733 Handle<Code> StubCache::ComputeCallGlobal(int argc, | 651 Handle<Code> StubCache::ComputeCallGlobal(int argc, |
734 Code::Kind kind, | 652 Code::Kind kind, |
735 Code::ExtraICState extra_state, | 653 Code::ExtraICState extra_state, |
736 Handle<String> name, | 654 Handle<String> name, |
737 Handle<JSObject> receiver, | 655 Handle<JSObject> receiver, |
738 Handle<GlobalObject> holder, | 656 Handle<GlobalObject> holder, |
739 Handle<JSGlobalPropertyCell> cell, | 657 Handle<JSGlobalPropertyCell> cell, |
740 Handle<JSFunction> function) { | 658 Handle<JSFunction> function) { |
741 InlineCacheHolderFlag cache_holder = | 659 InlineCacheHolderFlag cache_holder = |
742 IC::GetCodeCacheForObject(*receiver, *holder); | 660 IC::GetCodeCacheForObject(*receiver, *holder); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 int entry = cache->FindEntry(isolate_, flags); | 817 int entry = cache->FindEntry(isolate_, flags); |
900 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 818 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
901 | 819 |
902 StubCompiler compiler(isolate_); | 820 StubCompiler compiler(isolate_); |
903 Handle<Code> code = compiler.CompileCallMiss(flags); | 821 Handle<Code> code = compiler.CompileCallMiss(flags); |
904 FillCache(isolate_, code); | 822 FillCache(isolate_, code); |
905 return code; | 823 return code; |
906 } | 824 } |
907 | 825 |
908 | 826 |
909 // The CallStubCompiler needs a version of ComputeCallMiss that does not | |
910 // perform GC. This function is temporary, because the stub cache but not | |
911 // yet the stub compiler uses handles. | |
912 MaybeObject* StubCache::TryComputeCallMiss(int argc, | |
913 Code::Kind kind, | |
914 Code::ExtraICState extra_state) { | |
915 Code::Flags flags = | |
916 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state, | |
917 NORMAL, argc, OWN_MAP); | |
918 NumberDictionary* cache = isolate_->heap()->non_monomorphic_cache(); | |
919 int entry = cache->FindEntry(isolate_, flags); | |
920 if (entry != -1) return cache->ValueAt(entry); | |
921 | |
922 StubCompiler compiler(isolate_); | |
923 Code* code = NULL; | |
924 MaybeObject* maybe_code = compiler.TryCompileCallMiss(flags); | |
925 if (!maybe_code->To(&code)) return maybe_code; | |
926 | |
927 NumberDictionary* new_cache = NULL; | |
928 MaybeObject* maybe_new_cache = cache->AtNumberPut(flags, code); | |
929 if (!maybe_new_cache->To(&new_cache)) return maybe_new_cache; | |
930 isolate_->heap()->public_set_non_monomorphic_cache(new_cache); | |
931 | |
932 return code; | |
933 } | |
934 | |
935 | |
936 #ifdef ENABLE_DEBUGGER_SUPPORT | 827 #ifdef ENABLE_DEBUGGER_SUPPORT |
937 Handle<Code> StubCache::ComputeCallDebugBreak(int argc, | 828 Handle<Code> StubCache::ComputeCallDebugBreak(int argc, |
938 Code::Kind kind) { | 829 Code::Kind kind) { |
939 // Extra IC state is irrelevant for debug break ICs. They jump to | 830 // Extra IC state is irrelevant for debug break ICs. They jump to |
940 // the actual call ic to carry out the work. | 831 // the actual call ic to carry out the work. |
941 Code::Flags flags = | 832 Code::Flags flags = |
942 Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState, | 833 Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState, |
943 NORMAL, argc); | 834 NORMAL, argc); |
944 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); | 835 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); |
945 int entry = cache->FindEntry(isolate_, flags); | 836 int entry = cache->FindEntry(isolate_, flags); |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss"); | 1227 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss"); |
1337 isolate()->counters()->call_megamorphic_stubs()->Increment(); | 1228 isolate()->counters()->call_megamorphic_stubs()->Increment(); |
1338 PROFILE(isolate(), | 1229 PROFILE(isolate(), |
1339 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), | 1230 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), |
1340 *code, code->arguments_count())); | 1231 *code, code->arguments_count())); |
1341 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code)); | 1232 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code)); |
1342 return code; | 1233 return code; |
1343 } | 1234 } |
1344 | 1235 |
1345 | 1236 |
1346 // TODO(kmillikin): This annoying raw pointer implementation should be | |
1347 // eliminated when the stub compiler no longer needs it. | |
1348 MaybeObject* StubCompiler::TryCompileCallMiss(Code::Flags flags) { | |
1349 HandleScope scope(isolate()); | |
1350 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
1351 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
1352 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
1353 if (kind == Code::CALL_IC) { | |
1354 CallIC::GenerateMiss(masm(), argc, extra_state); | |
1355 } else { | |
1356 KeyedCallIC::GenerateMiss(masm(), argc); | |
1357 } | |
1358 Object* result; | |
1359 { MaybeObject* maybe_result = TryGetCodeWithFlags(flags, "CompileCallMiss"); | |
1360 if (!maybe_result->ToObject(&result)) return maybe_result; | |
1361 } | |
1362 isolate()->counters()->call_megamorphic_stubs()->Increment(); | |
1363 Code* code = Code::cast(result); | |
1364 USE(code); | |
1365 PROFILE(isolate(), | |
1366 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), | |
1367 code, code->arguments_count())); | |
1368 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code))); | |
1369 return result; | |
1370 } | |
1371 | |
1372 | |
1373 #ifdef ENABLE_DEBUGGER_SUPPORT | 1237 #ifdef ENABLE_DEBUGGER_SUPPORT |
1374 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | 1238 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) { |
1375 Debug::GenerateCallICDebugBreak(masm()); | 1239 Debug::GenerateCallICDebugBreak(masm()); |
1376 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak"); | 1240 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak"); |
1377 PROFILE(isolate(), | 1241 PROFILE(isolate(), |
1378 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), | 1242 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), |
1379 CALL_DEBUG_BREAK_TAG), | 1243 CALL_DEBUG_BREAK_TAG), |
1380 *code, code->arguments_count())); | 1244 *code, code->arguments_count())); |
1381 return code; | 1245 return code; |
1382 } | 1246 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1447 | 1311 |
1448 MaybeObject* StubCompiler::TryGetCodeWithFlags(Code::Flags flags, | 1312 MaybeObject* StubCompiler::TryGetCodeWithFlags(Code::Flags flags, |
1449 String* name) { | 1313 String* name) { |
1450 if (FLAG_print_code_stubs && name != NULL) { | 1314 if (FLAG_print_code_stubs && name != NULL) { |
1451 return TryGetCodeWithFlags(flags, *name->ToCString()); | 1315 return TryGetCodeWithFlags(flags, *name->ToCString()); |
1452 } | 1316 } |
1453 return TryGetCodeWithFlags(flags, reinterpret_cast<char*>(NULL)); | 1317 return TryGetCodeWithFlags(flags, reinterpret_cast<char*>(NULL)); |
1454 } | 1318 } |
1455 | 1319 |
1456 | 1320 |
1457 void StubCompiler::LookupPostInterceptor(JSObject* holder, | 1321 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, |
1458 String* name, | 1322 Handle<String> name, |
1459 LookupResult* lookup) { | 1323 LookupResult* lookup) { |
1460 holder->LocalLookupRealNamedProperty(name, lookup); | 1324 holder->LocalLookupRealNamedProperty(*name, lookup); |
1461 if (!lookup->IsProperty()) { | 1325 if (lookup->IsProperty()) return; |
1462 lookup->NotFound(); | 1326 |
1463 Object* proto = holder->GetPrototype(); | 1327 lookup->NotFound(); |
1464 if (!proto->IsNull()) { | 1328 if (holder->GetPrototype()->IsNull()) return; |
1465 proto->Lookup(name, lookup); | 1329 |
1466 } | 1330 holder->GetPrototype()->Lookup(*name, lookup); |
1467 } | |
1468 } | 1331 } |
1469 | 1332 |
1470 | 1333 |
1471 Handle<Code> LoadStubCompiler::GetCode(PropertyType type, Handle<String> name) { | 1334 Handle<Code> LoadStubCompiler::GetCode(PropertyType type, Handle<String> name) { |
1472 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type); | 1335 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type); |
1473 Handle<Code> code = GetCodeWithFlags(flags, name); | 1336 Handle<Code> code = GetCodeWithFlags(flags, name); |
1474 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 1337 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); |
1475 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 1338 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
1476 return code; | 1339 return code; |
1477 } | 1340 } |
1478 | 1341 |
1479 | 1342 |
1480 // TODO(ulan): Eliminate this function when the stub cache is fully | |
1481 // handlified. | |
1482 MaybeObject* LoadStubCompiler::TryGetCode(PropertyType type, String* name) { | |
1483 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type); | |
1484 MaybeObject* result = TryGetCodeWithFlags(flags, name); | |
1485 if (!result->IsFailure()) { | |
1486 PROFILE(isolate(), | |
1487 CodeCreateEvent(Logger::LOAD_IC_TAG, | |
1488 Code::cast(result->ToObjectUnchecked()), | |
1489 name)); | |
1490 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, | |
1491 name, | |
1492 Code::cast(result->ToObjectUnchecked()))); | |
1493 } | |
1494 return result; | |
1495 } | |
1496 | |
1497 | |
1498 Handle<Code> KeyedLoadStubCompiler::GetCode(PropertyType type, | 1343 Handle<Code> KeyedLoadStubCompiler::GetCode(PropertyType type, |
1499 Handle<String> name, | 1344 Handle<String> name, |
1500 InlineCacheState state) { | 1345 InlineCacheState state) { |
1501 Code::Flags flags = Code::ComputeFlags( | 1346 Code::Flags flags = Code::ComputeFlags( |
1502 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); | 1347 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); |
1503 Handle<Code> code = GetCodeWithFlags(flags, name); | 1348 Handle<Code> code = GetCodeWithFlags(flags, name); |
1504 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 1349 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); |
1505 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 1350 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
1506 return code; | 1351 return code; |
1507 } | 1352 } |
1508 | 1353 |
1509 // TODO(ulan): Eliminate this function when the stub cache is fully | |
1510 // handlified. | |
1511 MaybeObject* KeyedLoadStubCompiler::TryGetCode(PropertyType type, | |
1512 String* name, | |
1513 InlineCacheState state) { | |
1514 Code::Flags flags = Code::ComputeFlags( | |
1515 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); | |
1516 MaybeObject* result = TryGetCodeWithFlags(flags, name); | |
1517 if (!result->IsFailure()) { | |
1518 PROFILE(isolate(), | |
1519 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, | |
1520 Code::cast(result->ToObjectUnchecked()), | |
1521 name)); | |
1522 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, | |
1523 name, | |
1524 Code::cast(result->ToObjectUnchecked()))); | |
1525 } | |
1526 return result; | |
1527 } | |
1528 | |
1529 | 1354 |
1530 Handle<Code> StoreStubCompiler::GetCode(PropertyType type, | 1355 Handle<Code> StoreStubCompiler::GetCode(PropertyType type, |
1531 Handle<String> name) { | 1356 Handle<String> name) { |
1532 Code::Flags flags = | 1357 Code::Flags flags = |
1533 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_); | 1358 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_); |
1534 Handle<Code> code = GetCodeWithFlags(flags, name); | 1359 Handle<Code> code = GetCodeWithFlags(flags, name); |
1535 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | 1360 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
1536 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | 1361 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
1537 return code; | 1362 return code; |
1538 } | 1363 } |
(...skipping 23 matching lines...) Expand all Loading... |
1562 Code::ExtraICState extra_state, | 1387 Code::ExtraICState extra_state, |
1563 InlineCacheHolderFlag cache_holder) | 1388 InlineCacheHolderFlag cache_holder) |
1564 : StubCompiler(isolate), | 1389 : StubCompiler(isolate), |
1565 arguments_(argc), | 1390 arguments_(argc), |
1566 kind_(kind), | 1391 kind_(kind), |
1567 extra_state_(extra_state), | 1392 extra_state_(extra_state), |
1568 cache_holder_(cache_holder) { | 1393 cache_holder_(cache_holder) { |
1569 } | 1394 } |
1570 | 1395 |
1571 | 1396 |
1572 bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) { | 1397 bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) { |
1573 SharedFunctionInfo* info = function->shared(); | 1398 if (function->shared()->HasBuiltinFunctionId()) { |
1574 if (info->HasBuiltinFunctionId()) { | 1399 BuiltinFunctionId id = function->shared()->builtin_function_id(); |
1575 BuiltinFunctionId id = info->builtin_function_id(); | |
1576 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true; | 1400 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true; |
1577 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1401 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) |
1578 #undef CALL_GENERATOR_CASE | 1402 #undef CALL_GENERATOR_CASE |
1579 } | 1403 } |
| 1404 |
1580 CallOptimization optimization(function); | 1405 CallOptimization optimization(function); |
1581 if (optimization.is_simple_api_call()) { | 1406 return optimization.is_simple_api_call(); |
1582 return true; | |
1583 } | |
1584 return false; | |
1585 } | 1407 } |
1586 | 1408 |
1587 | 1409 |
1588 MaybeObject* CallStubCompiler::CompileCustomCall(Object* object, | 1410 Handle<Code> CallStubCompiler::CompileCustomCall( |
1589 JSObject* holder, | 1411 Handle<Object> object, |
1590 JSGlobalPropertyCell* cell, | 1412 Handle<JSObject> holder, |
1591 JSFunction* function, | 1413 Handle<JSGlobalPropertyCell> cell, |
1592 String* fname) { | 1414 Handle<JSFunction> function, |
| 1415 Handle<String> fname) { |
1593 ASSERT(HasCustomCallGenerator(function)); | 1416 ASSERT(HasCustomCallGenerator(function)); |
1594 | 1417 |
1595 SharedFunctionInfo* info = function->shared(); | 1418 if (function->shared()->HasBuiltinFunctionId()) { |
1596 if (info->HasBuiltinFunctionId()) { | 1419 BuiltinFunctionId id = function->shared()->builtin_function_id(); |
1597 BuiltinFunctionId id = info->builtin_function_id(); | 1420 #define CALL_GENERATOR_CASE(name) \ |
1598 #define CALL_GENERATOR_CASE(name) \ | 1421 if (id == k##name) { \ |
1599 if (id == k##name) { \ | 1422 return CallStubCompiler::Compile##name##Call(object, \ |
1600 return CallStubCompiler::Compile##name##Call(object, \ | 1423 holder, \ |
1601 holder, \ | 1424 cell, \ |
1602 cell, \ | 1425 function, \ |
1603 function, \ | 1426 fname); \ |
1604 fname); \ | |
1605 } | 1427 } |
1606 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1428 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) |
1607 #undef CALL_GENERATOR_CASE | 1429 #undef CALL_GENERATOR_CASE |
1608 } | 1430 } |
1609 CallOptimization optimization(function); | 1431 CallOptimization optimization(function); |
1610 ASSERT(optimization.is_simple_api_call()); | 1432 ASSERT(optimization.is_simple_api_call()); |
1611 return CompileFastApiCall(optimization, | 1433 return CompileFastApiCall(optimization, |
1612 object, | 1434 object, |
1613 holder, | 1435 holder, |
1614 cell, | 1436 cell, |
(...skipping 15 matching lines...) Expand all Loading... |
1630 | 1452 |
1631 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { | 1453 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { |
1632 Handle<String> function_name; | 1454 Handle<String> function_name; |
1633 if (function->shared()->name()->IsString()) { | 1455 if (function->shared()->name()->IsString()) { |
1634 function_name = Handle<String>(String::cast(function->shared()->name())); | 1456 function_name = Handle<String>(String::cast(function->shared()->name())); |
1635 } | 1457 } |
1636 return GetCode(CONSTANT_FUNCTION, function_name); | 1458 return GetCode(CONSTANT_FUNCTION, function_name); |
1637 } | 1459 } |
1638 | 1460 |
1639 | 1461 |
1640 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
1641 // handlified. | |
1642 MaybeObject* CallStubCompiler::TryGetCode(PropertyType type, String* name) { | |
1643 int argc = arguments_.immediate(); | |
1644 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, | |
1645 type, | |
1646 extra_state_, | |
1647 cache_holder_, | |
1648 argc); | |
1649 return TryGetCodeWithFlags(flags, name); | |
1650 } | |
1651 | |
1652 | |
1653 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
1654 // handlified. | |
1655 MaybeObject* CallStubCompiler::TryGetCode(JSFunction* function) { | |
1656 String* function_name = NULL; | |
1657 if (function->shared()->name()->IsString()) { | |
1658 function_name = String::cast(function->shared()->name()); | |
1659 } | |
1660 return TryGetCode(CONSTANT_FUNCTION, function_name); | |
1661 } | |
1662 | |
1663 | |
1664 MaybeObject* ConstructStubCompiler::GetCode() { | 1462 MaybeObject* ConstructStubCompiler::GetCode() { |
1665 Code::Flags flags = Code::ComputeFlags(Code::STUB); | 1463 Code::Flags flags = Code::ComputeFlags(Code::STUB); |
1666 Object* result; | 1464 Object* result; |
1667 { MaybeObject* maybe_result = TryGetCodeWithFlags(flags, "ConstructStub"); | 1465 { MaybeObject* maybe_result = TryGetCodeWithFlags(flags, "ConstructStub"); |
1668 if (!maybe_result->ToObject(&result)) return maybe_result; | 1466 if (!maybe_result->ToObject(&result)) return maybe_result; |
1669 } | 1467 } |
1670 Code* code = Code::cast(result); | 1468 Code* code = Code::cast(result); |
1671 USE(code); | 1469 USE(code); |
1672 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub")); | 1470 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub")); |
1673 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code))); | 1471 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code))); |
1674 return result; | 1472 return result; |
1675 } | 1473 } |
1676 | 1474 |
1677 | 1475 |
1678 CallOptimization::CallOptimization(LookupResult* lookup) { | 1476 CallOptimization::CallOptimization(LookupResult* lookup) { |
1679 if (!lookup->IsProperty() || !lookup->IsCacheable() || | 1477 if (!lookup->IsProperty() || |
| 1478 !lookup->IsCacheable() || |
1680 lookup->type() != CONSTANT_FUNCTION) { | 1479 lookup->type() != CONSTANT_FUNCTION) { |
1681 Initialize(NULL); | 1480 Initialize(Handle<JSFunction>::null()); |
1682 } else { | 1481 } else { |
1683 // We only optimize constant function calls. | 1482 // We only optimize constant function calls. |
1684 Initialize(lookup->GetConstantFunction()); | 1483 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); |
1685 } | 1484 } |
1686 } | 1485 } |
1687 | 1486 |
1688 CallOptimization::CallOptimization(JSFunction* function) { | 1487 CallOptimization::CallOptimization(Handle<JSFunction> function) { |
1689 Initialize(function); | 1488 Initialize(function); |
1690 } | 1489 } |
1691 | 1490 |
1692 | 1491 |
1693 int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object, | 1492 int CallOptimization::GetPrototypeDepthOfExpectedType( |
1694 JSObject* holder) const { | 1493 Handle<JSObject> object, |
1695 ASSERT(is_simple_api_call_); | 1494 Handle<JSObject> holder) const { |
1696 if (expected_receiver_type_ == NULL) return 0; | 1495 ASSERT(is_simple_api_call()); |
| 1496 if (expected_receiver_type_.is_null()) return 0; |
1697 int depth = 0; | 1497 int depth = 0; |
1698 while (object != holder) { | 1498 while (!object.is_identical_to(holder)) { |
1699 if (object->IsInstanceOf(expected_receiver_type_)) return depth; | 1499 if (object->IsInstanceOf(*expected_receiver_type_)) return depth; |
1700 object = JSObject::cast(object->GetPrototype()); | 1500 object = Handle<JSObject>(JSObject::cast(object->GetPrototype())); |
1701 ++depth; | 1501 ++depth; |
1702 } | 1502 } |
1703 if (holder->IsInstanceOf(expected_receiver_type_)) return depth; | 1503 if (holder->IsInstanceOf(*expected_receiver_type_)) return depth; |
1704 return kInvalidProtoDepth; | 1504 return kInvalidProtoDepth; |
1705 } | 1505 } |
1706 | 1506 |
1707 | 1507 |
1708 void CallOptimization::Initialize(JSFunction* function) { | 1508 void CallOptimization::Initialize(Handle<JSFunction> function) { |
1709 constant_function_ = NULL; | 1509 constant_function_ = Handle<JSFunction>::null(); |
1710 is_simple_api_call_ = false; | 1510 is_simple_api_call_ = false; |
1711 expected_receiver_type_ = NULL; | 1511 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); |
1712 api_call_info_ = NULL; | 1512 api_call_info_ = Handle<CallHandlerInfo>::null(); |
1713 | 1513 |
1714 if (function == NULL || !function->is_compiled()) return; | 1514 if (function.is_null() || !function->is_compiled()) return; |
1715 | 1515 |
1716 constant_function_ = function; | 1516 constant_function_ = function; |
1717 AnalyzePossibleApiFunction(function); | 1517 AnalyzePossibleApiFunction(function); |
1718 } | 1518 } |
1719 | 1519 |
1720 | 1520 |
1721 void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) { | 1521 void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) { |
1722 SharedFunctionInfo* sfi = function->shared(); | 1522 if (!function->shared()->IsApiFunction()) return; |
1723 if (!sfi->IsApiFunction()) return; | 1523 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data()); |
1724 FunctionTemplateInfo* info = sfi->get_api_func_data(); | |
1725 | 1524 |
1726 // Require a C++ callback. | 1525 // Require a C++ callback. |
1727 if (info->call_code()->IsUndefined()) return; | 1526 if (info->call_code()->IsUndefined()) return; |
1728 api_call_info_ = CallHandlerInfo::cast(info->call_code()); | 1527 api_call_info_ = |
| 1528 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code())); |
1729 | 1529 |
1730 // Accept signatures that either have no restrictions at all or | 1530 // Accept signatures that either have no restrictions at all or |
1731 // only have restrictions on the receiver. | 1531 // only have restrictions on the receiver. |
1732 if (!info->signature()->IsUndefined()) { | 1532 if (!info->signature()->IsUndefined()) { |
1733 SignatureInfo* signature = SignatureInfo::cast(info->signature()); | 1533 Handle<SignatureInfo> signature = |
| 1534 Handle<SignatureInfo>(SignatureInfo::cast(info->signature())); |
1734 if (!signature->args()->IsUndefined()) return; | 1535 if (!signature->args()->IsUndefined()) return; |
1735 if (!signature->receiver()->IsUndefined()) { | 1536 if (!signature->receiver()->IsUndefined()) { |
1736 expected_receiver_type_ = | 1537 expected_receiver_type_ = |
1737 FunctionTemplateInfo::cast(signature->receiver()); | 1538 Handle<FunctionTemplateInfo>( |
| 1539 FunctionTemplateInfo::cast(signature->receiver())); |
1738 } | 1540 } |
1739 } | 1541 } |
1740 | 1542 |
1741 is_simple_api_call_ = true; | 1543 is_simple_api_call_ = true; |
1742 } | 1544 } |
1743 | 1545 |
1744 | 1546 |
1745 } } // namespace v8::internal | 1547 } } // namespace v8::internal |
OLD | NEW |