OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 26 matching lines...) Expand all Loading... |
37 | 37 |
38 #include "ic-inl.h" | 38 #include "ic-inl.h" |
39 #include "objects-inl.h" | 39 #include "objects-inl.h" |
40 | 40 |
41 namespace v8 { | 41 namespace v8 { |
42 namespace internal { | 42 namespace internal { |
43 | 43 |
44 | 44 |
45 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 45 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
46 Handle<Context> native_context, | 46 Handle<Context> native_context, |
47 Isolate* isolate, | |
48 Zone* zone) | 47 Zone* zone) |
49 : native_context_(native_context), | 48 : native_context_(native_context), |
50 isolate_(isolate), | |
51 zone_(zone) { | 49 zone_(zone) { |
52 BuildDictionary(code); | 50 BuildDictionary(code); |
53 ASSERT(dictionary_->IsDictionary()); | 51 ASSERT(dictionary_->IsDictionary()); |
54 } | 52 } |
55 | 53 |
56 | 54 |
57 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 55 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
58 return static_cast<uint32_t>(ast_id.ToInt()); | 56 return static_cast<uint32_t>(ast_id.ToInt()); |
59 } | 57 } |
60 | 58 |
61 | 59 |
62 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 60 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
63 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 61 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
64 if (entry != UnseededNumberDictionary::kNotFound) { | 62 if (entry != UnseededNumberDictionary::kNotFound) { |
65 Object* value = dictionary_->ValueAt(entry); | 63 Object* value = dictionary_->ValueAt(entry); |
66 if (value->IsCell()) { | 64 if (value->IsCell()) { |
67 Cell* cell = Cell::cast(value); | 65 Cell* cell = Cell::cast(value); |
68 return Handle<Object>(cell->value(), isolate_); | 66 return Handle<Object>(cell->value(), isolate()); |
69 } else { | 67 } else { |
70 return Handle<Object>(value, isolate_); | 68 return Handle<Object>(value, isolate()); |
71 } | 69 } |
72 } | 70 } |
73 return Handle<Object>::cast(isolate_->factory()->undefined_value()); | 71 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
74 } | 72 } |
75 | 73 |
76 | 74 |
77 Handle<Cell> TypeFeedbackOracle::GetInfoCell( | 75 Handle<Cell> TypeFeedbackOracle::GetInfoCell( |
78 TypeFeedbackId ast_id) { | 76 TypeFeedbackId ast_id) { |
79 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 77 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
80 if (entry != UnseededNumberDictionary::kNotFound) { | 78 if (entry != UnseededNumberDictionary::kNotFound) { |
81 Cell* cell = Cell::cast(dictionary_->ValueAt(entry)); | 79 Cell* cell = Cell::cast(dictionary_->ValueAt(entry)); |
82 return Handle<Cell>(cell, isolate_); | 80 return Handle<Cell>(cell, isolate()); |
83 } | 81 } |
84 return Handle<Cell>::null(); | 82 return Handle<Cell>::null(); |
85 } | 83 } |
86 | 84 |
87 | 85 |
88 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 86 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
89 Handle<Object> maybe_code = GetInfo(id); | 87 Handle<Object> maybe_code = GetInfo(id); |
90 if (maybe_code->IsCode()) { | 88 if (maybe_code->IsCode()) { |
91 Handle<Code> code = Handle<Code>::cast(maybe_code); | 89 Handle<Code> code = Handle<Code>::cast(maybe_code); |
92 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; | 90 return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; | 197 if (!value->IsSmi()) return RECEIVER_MAP_CHECK; |
200 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); | 198 CheckType check = static_cast<CheckType>(Smi::cast(*value)->value()); |
201 ASSERT(check != RECEIVER_MAP_CHECK); | 199 ASSERT(check != RECEIVER_MAP_CHECK); |
202 return check; | 200 return check; |
203 } | 201 } |
204 | 202 |
205 | 203 |
206 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { | 204 Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) { |
207 Handle<Object> info = GetInfo(id); | 205 Handle<Object> info = GetInfo(id); |
208 if (info->IsAllocationSite()) { | 206 if (info->IsAllocationSite()) { |
209 return Handle<JSFunction>(isolate_->global_context()->array_function()); | 207 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
210 } else { | 208 } else { |
211 return Handle<JSFunction>::cast(info); | 209 return Handle<JSFunction>::cast(info); |
212 } | 210 } |
213 } | 211 } |
214 | 212 |
215 | 213 |
216 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { | 214 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) { |
217 Handle<Object> info = GetInfo(id); | 215 Handle<Object> info = GetInfo(id); |
218 if (info->IsAllocationSite()) { | 216 if (info->IsAllocationSite()) { |
219 return Handle<JSFunction>(isolate_->global_context()->array_function()); | 217 return Handle<JSFunction>(isolate()->global_context()->array_function()); |
220 } else { | 218 } else { |
221 return Handle<JSFunction>::cast(info); | 219 return Handle<JSFunction>::cast(info); |
222 } | 220 } |
223 } | 221 } |
224 | 222 |
225 | 223 |
226 Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell( | 224 Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell( |
227 TypeFeedbackId id) { | 225 TypeFeedbackId id) { |
228 return GetInfoCell(id); | 226 return GetInfoCell(id); |
229 } | 227 } |
230 | 228 |
231 | 229 |
232 bool TypeFeedbackOracle::LoadIsBuiltin( | 230 bool TypeFeedbackOracle::LoadIsBuiltin( |
233 TypeFeedbackId id, Builtins::Name builtin) { | 231 TypeFeedbackId id, Builtins::Name builtin) { |
234 return *GetInfo(id) == isolate_->builtins()->builtin(builtin); | 232 return *GetInfo(id) == isolate()->builtins()->builtin(builtin); |
235 } | 233 } |
236 | 234 |
237 | 235 |
238 bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) { | 236 bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) { |
239 Handle<Object> object = GetInfo(id); | 237 Handle<Object> object = GetInfo(id); |
240 if (!object->IsCode()) return false; | 238 if (!object->IsCode()) return false; |
241 Handle<Code> code = Handle<Code>::cast(object); | 239 Handle<Code> code = Handle<Code>::cast(object); |
242 if (!code->is_load_stub()) return false; | 240 if (!code->is_load_stub()) return false; |
243 if (code->ic_state() != MONOMORPHIC) return false; | 241 if (code->ic_state() != MONOMORPHIC) return false; |
244 return stub->Describes(*code); | 242 return stub->Describes(*code); |
245 } | 243 } |
246 | 244 |
247 | 245 |
248 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, | 246 void TypeFeedbackOracle::CompareType(TypeFeedbackId id, |
249 Handle<Type>* left_type, | 247 Type** left_type, |
250 Handle<Type>* right_type, | 248 Type** right_type, |
251 Handle<Type>* combined_type) { | 249 Type** combined_type) { |
252 Handle<Object> info = GetInfo(id); | 250 Handle<Object> info = GetInfo(id); |
253 if (!info->IsCode()) { | 251 if (!info->IsCode()) { |
254 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. | 252 // For some comparisons we don't have ICs, e.g. LiteralCompareTypeof. |
255 *left_type = *right_type = *combined_type = Type::None(isolate_); | 253 *left_type = *right_type = *combined_type = Type::None(zone()); |
256 return; | 254 return; |
257 } | 255 } |
258 Handle<Code> code = Handle<Code>::cast(info); | 256 Handle<Code> code = Handle<Code>::cast(info); |
259 | 257 |
260 Handle<Map> map; | 258 Handle<Map> map; |
261 Map* raw_map = code->FindFirstMap(); | 259 Map* raw_map = code->FindFirstMap(); |
262 if (raw_map != NULL) { | 260 if (raw_map != NULL) { |
263 map = Map::CurrentMapForDeprecated(handle(raw_map)); | 261 map = Map::CurrentMapForDeprecated(handle(raw_map)); |
264 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { | 262 if (!map.is_null() && CanRetainOtherContext(*map, *native_context_)) { |
265 map = Handle<Map>::null(); | 263 map = Handle<Map>::null(); |
266 } | 264 } |
267 } | 265 } |
268 | 266 |
269 if (code->is_compare_ic_stub()) { | 267 if (code->is_compare_ic_stub()) { |
270 int stub_minor_key = code->stub_info(); | 268 int stub_minor_key = code->stub_info(); |
271 CompareIC::StubInfoToType( | 269 CompareIC::StubInfoToType( |
272 stub_minor_key, left_type, right_type, combined_type, map, isolate()); | 270 stub_minor_key, left_type, right_type, combined_type, map, zone()); |
273 } else if (code->is_compare_nil_ic_stub()) { | 271 } else if (code->is_compare_nil_ic_stub()) { |
274 CompareNilICStub stub(code->extended_extra_ic_state()); | 272 CompareNilICStub stub(code->extended_extra_ic_state()); |
275 *combined_type = stub.GetType(isolate_, map); | 273 *combined_type = stub.GetType(zone(), map); |
276 *left_type = *right_type = stub.GetInputType(isolate_, map); | 274 *left_type = *right_type = stub.GetInputType(zone(), map); |
277 } | 275 } |
278 } | 276 } |
279 | 277 |
280 | 278 |
281 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, | 279 void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, |
282 Handle<Type>* left, | 280 Type** left, |
283 Handle<Type>* right, | 281 Type** right, |
284 Handle<Type>* result, | 282 Type** result, |
285 Maybe<int>* fixed_right_arg, | 283 Maybe<int>* fixed_right_arg, |
286 Token::Value op) { | 284 Token::Value op) { |
287 Handle<Object> object = GetInfo(id); | 285 Handle<Object> object = GetInfo(id); |
288 if (!object->IsCode()) { | 286 if (!object->IsCode()) { |
289 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the | 287 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the |
290 // operations covered by the BinaryOpIC we should always have them. | 288 // operations covered by the BinaryOpIC we should always have them. |
291 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || | 289 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || |
292 op > BinaryOpIC::State::LAST_TOKEN); | 290 op > BinaryOpIC::State::LAST_TOKEN); |
293 *left = *right = *result = Type::None(isolate_); | 291 *left = *right = *result = Type::None(zone()); |
294 *fixed_right_arg = Maybe<int>(); | 292 *fixed_right_arg = Maybe<int>(); |
295 return; | 293 return; |
296 } | 294 } |
297 Handle<Code> code = Handle<Code>::cast(object); | 295 Handle<Code> code = Handle<Code>::cast(object); |
298 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 296 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
299 BinaryOpIC::State state(code->extended_extra_ic_state()); | 297 BinaryOpIC::State state(code->extended_extra_ic_state()); |
300 ASSERT_EQ(op, state.op()); | 298 ASSERT_EQ(op, state.op()); |
301 | 299 |
302 *left = state.GetLeftType(isolate()); | 300 *left = state.GetLeftType(zone()); |
303 *right = state.GetRightType(isolate()); | 301 *right = state.GetRightType(zone()); |
304 *result = state.GetResultType(isolate()); | 302 *result = state.GetResultType(zone()); |
305 *fixed_right_arg = state.fixed_right_arg(); | 303 *fixed_right_arg = state.fixed_right_arg(); |
306 } | 304 } |
307 | 305 |
308 | 306 |
309 Handle<Type> TypeFeedbackOracle::CountType(TypeFeedbackId id) { | 307 Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) { |
310 Handle<Object> object = GetInfo(id); | 308 Handle<Object> object = GetInfo(id); |
311 if (!object->IsCode()) return Type::None(isolate_); | 309 if (!object->IsCode()) return Type::None(zone()); |
312 Handle<Code> code = Handle<Code>::cast(object); | 310 Handle<Code> code = Handle<Code>::cast(object); |
313 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 311 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); |
314 BinaryOpIC::State state(code->extended_extra_ic_state()); | 312 BinaryOpIC::State state(code->extended_extra_ic_state()); |
315 return state.GetLeftType(isolate()); | 313 return state.GetLeftType(zone()); |
316 } | 314 } |
317 | 315 |
318 | 316 |
319 void TypeFeedbackOracle::PropertyReceiverTypes( | 317 void TypeFeedbackOracle::PropertyReceiverTypes( |
320 TypeFeedbackId id, Handle<String> name, | 318 TypeFeedbackId id, Handle<String> name, |
321 SmallMapList* receiver_types, bool* is_prototype) { | 319 SmallMapList* receiver_types, bool* is_prototype) { |
322 receiver_types->Clear(); | 320 receiver_types->Clear(); |
323 FunctionPrototypeStub proto_stub(Code::LOAD_IC); | 321 FunctionPrototypeStub proto_stub(Code::LOAD_IC); |
324 *is_prototype = LoadIsStub(id, &proto_stub); | 322 *is_prototype = LoadIsStub(id, &proto_stub); |
325 if (!*is_prototype) { | 323 if (!*is_prototype) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 SmallMapList* types) { | 373 SmallMapList* types) { |
376 Handle<Object> object = GetInfo(ast_id); | 374 Handle<Object> object = GetInfo(ast_id); |
377 if (object->IsUndefined() || object->IsSmi()) return; | 375 if (object->IsUndefined() || object->IsSmi()) return; |
378 | 376 |
379 ASSERT(object->IsCode()); | 377 ASSERT(object->IsCode()); |
380 Handle<Code> code(Handle<Code>::cast(object)); | 378 Handle<Code> code(Handle<Code>::cast(object)); |
381 | 379 |
382 if (FLAG_collect_megamorphic_maps_from_stub_cache && | 380 if (FLAG_collect_megamorphic_maps_from_stub_cache && |
383 code->ic_state() == MEGAMORPHIC) { | 381 code->ic_state() == MEGAMORPHIC) { |
384 types->Reserve(4, zone()); | 382 types->Reserve(4, zone()); |
385 isolate_->stub_cache()->CollectMatchingMaps( | 383 isolate()->stub_cache()->CollectMatchingMaps( |
386 types, name, flags, native_context_, zone()); | 384 types, name, flags, native_context_, zone()); |
387 } else { | 385 } else { |
388 CollectReceiverTypes(ast_id, types); | 386 CollectReceiverTypes(ast_id, types); |
389 } | 387 } |
390 } | 388 } |
391 | 389 |
392 | 390 |
393 // Check if a map originates from a given native context. We use this | 391 // Check if a map originates from a given native context. We use this |
394 // information to filter out maps from different context to avoid | 392 // information to filter out maps from different context to avoid |
395 // retaining objects from different tabs in Chrome via optimized code. | 393 // retaining objects from different tabs in Chrome via optimized code. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 } | 452 } |
455 | 453 |
456 | 454 |
457 // Things are a bit tricky here: The iterator for the RelocInfos and the infos | 455 // Things are a bit tricky here: The iterator for the RelocInfos and the infos |
458 // themselves are not GC-safe, so we first get all infos, then we create the | 456 // themselves are not GC-safe, so we first get all infos, then we create the |
459 // dictionary (possibly triggering GC), and finally we relocate the collected | 457 // dictionary (possibly triggering GC), and finally we relocate the collected |
460 // infos before we process them. | 458 // infos before we process them. |
461 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { | 459 void TypeFeedbackOracle::BuildDictionary(Handle<Code> code) { |
462 DisallowHeapAllocation no_allocation; | 460 DisallowHeapAllocation no_allocation; |
463 ZoneList<RelocInfo> infos(16, zone()); | 461 ZoneList<RelocInfo> infos(16, zone()); |
464 HandleScope scope(isolate_); | 462 HandleScope scope(isolate()); |
465 GetRelocInfos(code, &infos); | 463 GetRelocInfos(code, &infos); |
466 CreateDictionary(code, &infos); | 464 CreateDictionary(code, &infos); |
467 ProcessRelocInfos(&infos); | 465 ProcessRelocInfos(&infos); |
468 ProcessTypeFeedbackCells(code); | 466 ProcessTypeFeedbackCells(code); |
469 // Allocate handle in the parent scope. | 467 // Allocate handle in the parent scope. |
470 dictionary_ = scope.CloseAndEscape(dictionary_); | 468 dictionary_ = scope.CloseAndEscape(dictionary_); |
471 } | 469 } |
472 | 470 |
473 | 471 |
474 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, | 472 void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 #ifdef DEBUG | 564 #ifdef DEBUG |
567 Object* result = NULL; | 565 Object* result = NULL; |
568 // Dictionary has been allocated with sufficient size for all elements. | 566 // Dictionary has been allocated with sufficient size for all elements. |
569 ASSERT(maybe_result->ToObject(&result)); | 567 ASSERT(maybe_result->ToObject(&result)); |
570 ASSERT(*dictionary_ == result); | 568 ASSERT(*dictionary_ == result); |
571 #endif | 569 #endif |
572 } | 570 } |
573 | 571 |
574 | 572 |
575 } } // namespace v8::internal | 573 } } // namespace v8::internal |
OLD | NEW |