Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: src/type-info.cc

Issue 7966038: Record function call targets, use them for inlining. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/type-info.h ('k') | src/v8globals.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 69
70 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { 70 Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) {
71 int entry = dictionary_->FindEntry(ast_id); 71 int entry = dictionary_->FindEntry(ast_id);
72 return entry != NumberDictionary::kNotFound 72 return entry != NumberDictionary::kNotFound
73 ? Handle<Object>(dictionary_->ValueAt(entry)) 73 ? Handle<Object>(dictionary_->ValueAt(entry))
74 : Isolate::Current()->factory()->undefined_value(); 74 : Isolate::Current()->factory()->undefined_value();
75 } 75 }
76 76
77 77
78 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { 78 bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) {
79 Handle<Object> map_or_code(GetInfo(expr->id())); 79 Handle<Object> map_or_code = GetInfo(expr->id());
80 if (map_or_code->IsMap()) return true; 80 if (map_or_code->IsMap()) return true;
81 if (map_or_code->IsCode()) { 81 if (map_or_code->IsCode()) {
82 Handle<Code> code = Handle<Code>::cast(map_or_code); 82 Handle<Code> code = Handle<Code>::cast(map_or_code);
83 return code->is_keyed_load_stub() && 83 return code->is_keyed_load_stub() &&
84 code->ic_state() == MONOMORPHIC && 84 code->ic_state() == MONOMORPHIC &&
85 Code::ExtractTypeFromFlags(code->flags()) == NORMAL && 85 Code::ExtractTypeFromFlags(code->flags()) == NORMAL &&
86 code->FindFirstMap() != NULL; 86 code->FindFirstMap() != NULL;
87 } 87 }
88 return false; 88 return false;
89 } 89 }
90 90
91 91
92 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) { 92 bool TypeFeedbackOracle::LoadIsMegamorphicWithTypeInfo(Property* expr) {
93 Handle<Object> map_or_code(GetInfo(expr->id())); 93 Handle<Object> map_or_code = GetInfo(expr->id());
94 if (map_or_code->IsCode()) { 94 if (map_or_code->IsCode()) {
95 Handle<Code> code = Handle<Code>::cast(map_or_code); 95 Handle<Code> code = Handle<Code>::cast(map_or_code);
96 Builtins* builtins = Isolate::Current()->builtins(); 96 Builtins* builtins = Isolate::Current()->builtins();
97 return code->is_keyed_load_stub() && 97 return code->is_keyed_load_stub() &&
98 *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) && 98 *code != builtins->builtin(Builtins::kKeyedLoadIC_Generic) &&
99 code->ic_state() == MEGAMORPHIC; 99 code->ic_state() == MEGAMORPHIC;
100 } 100 }
101 return false; 101 return false;
102 } 102 }
103 103
104 104
105 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) { 105 bool TypeFeedbackOracle::StoreIsMonomorphicNormal(Expression* expr) {
106 Handle<Object> map_or_code(GetInfo(expr->id())); 106 Handle<Object> map_or_code = GetInfo(expr->id());
107 if (map_or_code->IsMap()) return true; 107 if (map_or_code->IsMap()) return true;
108 if (map_or_code->IsCode()) { 108 if (map_or_code->IsCode()) {
109 Handle<Code> code = Handle<Code>::cast(map_or_code); 109 Handle<Code> code = Handle<Code>::cast(map_or_code);
110 return code->is_keyed_store_stub() && 110 return code->is_keyed_store_stub() &&
111 code->ic_state() == MONOMORPHIC && 111 code->ic_state() == MONOMORPHIC &&
112 Code::ExtractTypeFromFlags(code->flags()) == NORMAL; 112 Code::ExtractTypeFromFlags(code->flags()) == NORMAL;
113 } 113 }
114 return false; 114 return false;
115 } 115 }
116 116
117 117
118 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(Expression* expr) { 118 bool TypeFeedbackOracle::StoreIsMegamorphicWithTypeInfo(Expression* expr) {
119 Handle<Object> map_or_code(GetInfo(expr->id())); 119 Handle<Object> map_or_code = GetInfo(expr->id());
120 if (map_or_code->IsCode()) { 120 if (map_or_code->IsCode()) {
121 Handle<Code> code = Handle<Code>::cast(map_or_code); 121 Handle<Code> code = Handle<Code>::cast(map_or_code);
122 Builtins* builtins = Isolate::Current()->builtins(); 122 Builtins* builtins = Isolate::Current()->builtins();
123 return code->is_keyed_store_stub() && 123 return code->is_keyed_store_stub() &&
124 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic) && 124 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic) &&
125 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic_Strict) && 125 *code != builtins->builtin(Builtins::kKeyedStoreIC_Generic_Strict) &&
126 code->ic_state() == MEGAMORPHIC; 126 code->ic_state() == MEGAMORPHIC;
127 } 127 }
128 return false; 128 return false;
129 } 129 }
130 130
131 131
132 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) { 132 bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
133 Handle<Object> value = GetInfo(expr->id()); 133 Handle<Object> value = GetInfo(expr->id());
134 return value->IsMap() || value->IsSmi(); 134 return value->IsMap() || value->IsSmi() || value->IsJSFunction();
135 } 135 }
136 136
137 137
138 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) { 138 Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
139 ASSERT(LoadIsMonomorphicNormal(expr)); 139 ASSERT(LoadIsMonomorphicNormal(expr));
140 Handle<Object> map_or_code(GetInfo(expr->id())); 140 Handle<Object> map_or_code = GetInfo(expr->id());
141 if (map_or_code->IsCode()) { 141 if (map_or_code->IsCode()) {
142 Handle<Code> code = Handle<Code>::cast(map_or_code); 142 Handle<Code> code = Handle<Code>::cast(map_or_code);
143 Map* first_map = code->FindFirstMap(); 143 Map* first_map = code->FindFirstMap();
144 ASSERT(first_map != NULL); 144 ASSERT(first_map != NULL);
145 return Handle<Map>(first_map); 145 return Handle<Map>(first_map);
146 } 146 }
147 return Handle<Map>::cast(map_or_code); 147 return Handle<Map>::cast(map_or_code);
148 } 148 }
149 149
150 150
151 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) { 151 Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) {
152 ASSERT(StoreIsMonomorphicNormal(expr)); 152 ASSERT(StoreIsMonomorphicNormal(expr));
153 Handle<Object> map_or_code(GetInfo(expr->id())); 153 Handle<Object> map_or_code = GetInfo(expr->id());
154 if (map_or_code->IsCode()) { 154 if (map_or_code->IsCode()) {
155 Handle<Code> code = Handle<Code>::cast(map_or_code); 155 Handle<Code> code = Handle<Code>::cast(map_or_code);
156 return Handle<Map>(code->FindFirstMap()); 156 return Handle<Map>(code->FindFirstMap());
157 } 157 }
158 return Handle<Map>::cast(map_or_code); 158 return Handle<Map>::cast(map_or_code);
159 } 159 }
160 160
161 161
162 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr, 162 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
163 Handle<String> name, 163 Handle<String> name,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 196
197 197
198 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) { 198 CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
199 Handle<Object> value = GetInfo(expr->id()); 199 Handle<Object> value = GetInfo(expr->id());
200 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; 200 if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
201 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); 201 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
202 ASSERT(check != RECEIVER_MAP_CHECK); 202 ASSERT(check != RECEIVER_MAP_CHECK);
203 return check; 203 return check;
204 } 204 }
205 205
206
206 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck( 207 Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
207 CheckType check) { 208 CheckType check) {
208 JSFunction* function = NULL; 209 JSFunction* function = NULL;
209 switch (check) { 210 switch (check) {
210 case RECEIVER_MAP_CHECK: 211 case RECEIVER_MAP_CHECK:
211 UNREACHABLE(); 212 UNREACHABLE();
212 break; 213 break;
213 case STRING_CHECK: 214 case STRING_CHECK:
214 function = global_context_->string_function(); 215 function = global_context_->string_function();
215 break; 216 break;
216 case NUMBER_CHECK: 217 case NUMBER_CHECK:
217 function = global_context_->number_function(); 218 function = global_context_->number_function();
218 break; 219 break;
219 case BOOLEAN_CHECK: 220 case BOOLEAN_CHECK:
220 function = global_context_->boolean_function(); 221 function = global_context_->boolean_function();
221 break; 222 break;
222 } 223 }
223 ASSERT(function != NULL); 224 ASSERT(function != NULL);
224 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); 225 return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
225 } 226 }
226 227
227 228
229 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) {
230 return Handle<JSFunction>::cast(GetInfo(expr->id()));
231 }
232
233
228 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { 234 bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
229 return *GetInfo(expr->id()) == 235 return *GetInfo(expr->id()) ==
230 Isolate::Current()->builtins()->builtin(id); 236 Isolate::Current()->builtins()->builtin(id);
231 } 237 }
232 238
233 239
234 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { 240 TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
235 Handle<Object> object = GetInfo(expr->id()); 241 Handle<Object> object = GetInfo(expr->id());
236 TypeInfo unknown = TypeInfo::Unknown(); 242 TypeInfo unknown = TypeInfo::Unknown();
237 if (!object->IsCode()) return unknown; 243 if (!object->IsCode()) return unknown;
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 byte* new_start) { 487 byte* new_start) {
482 for (int i = 0; i < infos->length(); i++) { 488 for (int i = 0; i < infos->length(); i++) {
483 RelocInfo* info = &(*infos)[i]; 489 RelocInfo* info = &(*infos)[i];
484 info->set_pc(new_start + (info->pc() - old_start)); 490 info->set_pc(new_start + (info->pc() - old_start));
485 } 491 }
486 } 492 }
487 493
488 494
489 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { 495 void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
490 for (int i = 0; i < infos->length(); i++) { 496 for (int i = 0; i < infos->length(); i++) {
497 Address target_address = (*infos)[i].target_address();
491 unsigned ast_id = static_cast<unsigned>((*infos)[i].data()); 498 unsigned ast_id = static_cast<unsigned>((*infos)[i].data());
492 Code* target = Code::GetCodeFromTargetAddress((*infos)[i].target_address()); 499 ProcessTargetAt(target_address, ast_id);
493 ProcessTarget(ast_id, target);
494 } 500 }
495 } 501 }
496 502
497 503
498 void TypeFeedbackOracle::ProcessTarget(unsigned ast_id, Code* target) { 504 void TypeFeedbackOracle::ProcessTargetAt(Address target_address,
505 unsigned ast_id) {
506 Code* target = Code::GetCodeFromTargetAddress(target_address);
499 switch (target->kind()) { 507 switch (target->kind()) {
500 case Code::LOAD_IC: 508 case Code::LOAD_IC:
501 case Code::STORE_IC: 509 case Code::STORE_IC:
502 case Code::CALL_IC: 510 case Code::CALL_IC:
503 case Code::KEYED_CALL_IC: 511 case Code::KEYED_CALL_IC:
504 if (target->ic_state() == MONOMORPHIC) { 512 if (target->ic_state() == MONOMORPHIC) {
505 if (target->kind() == Code::CALL_IC && 513 if (target->kind() == Code::CALL_IC &&
506 target->check_type() != RECEIVER_MAP_CHECK) { 514 target->check_type() != RECEIVER_MAP_CHECK) {
507 SetInfo(ast_id, Smi::FromInt(target->check_type())); 515 SetInfo(ast_id, Smi::FromInt(target->check_type()));
508 } else { 516 } else {
509 Object* map = target->FindFirstMap(); 517 Object* map = target->FindFirstMap();
510 SetInfo(ast_id, map == NULL ? static_cast<Object*>(target) : map); 518 SetInfo(ast_id, map == NULL ? static_cast<Object*>(target) : map);
511 } 519 }
512 } else if (target->ic_state() == MEGAMORPHIC) { 520 } else if (target->ic_state() == MEGAMORPHIC) {
513 SetInfo(ast_id, target); 521 SetInfo(ast_id, target);
514 } 522 }
515 break; 523 break;
516 524
517 case Code::KEYED_LOAD_IC: 525 case Code::KEYED_LOAD_IC:
518 case Code::KEYED_STORE_IC: 526 case Code::KEYED_STORE_IC:
519 if (target->ic_state() == MONOMORPHIC || 527 if (target->ic_state() == MONOMORPHIC ||
520 target->ic_state() == MEGAMORPHIC) { 528 target->ic_state() == MEGAMORPHIC) {
521 SetInfo(ast_id, target); 529 SetInfo(ast_id, target);
522 } 530 }
523 break; 531 break;
524 532
525 case Code::UNARY_OP_IC: 533 case Code::UNARY_OP_IC:
526 case Code::BINARY_OP_IC: 534 case Code::BINARY_OP_IC:
527 case Code::COMPARE_IC: 535 case Code::COMPARE_IC:
528 case Code::TO_BOOLEAN_IC: 536 case Code::TO_BOOLEAN_IC:
529 SetInfo(ast_id, target); 537 SetInfo(ast_id, target);
530 break; 538 break;
531 539
540 case Code::STUB:
541 if (target->major_key() == CodeStub::CallFunction &&
542 target->has_function_cache()) {
543 Object* value = CallFunctionStub::GetCachedValue(target_address);
544 if (value->IsJSFunction()) {
545 SetInfo(ast_id, value);
546 }
547 }
548 break;
549
532 default: 550 default:
533 break; 551 break;
534 } 552 }
535 } 553 }
536 554
537 555
538 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { 556 void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) {
539 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound); 557 ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound);
540 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); 558 MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target);
541 USE(maybe_result); 559 USE(maybe_result);
542 #ifdef DEBUG 560 #ifdef DEBUG
543 Object* result = NULL; 561 Object* result = NULL;
544 // Dictionary has been allocated with sufficient size for all elements. 562 // Dictionary has been allocated with sufficient size for all elements.
545 ASSERT(maybe_result->ToObject(&result)); 563 ASSERT(maybe_result->ToObject(&result));
546 ASSERT(*dictionary_ == result); 564 ASSERT(*dictionary_ == result);
547 #endif 565 #endif
548 } 566 }
549 567
550 } } // namespace v8::internal 568 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/type-info.h ('k') | src/v8globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698