OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/ic.h" | 10 #include "src/ic.h" |
11 #include "src/macro-assembler.h" | 11 #include "src/macro-assembler.h" |
12 #include "src/stub-cache.h" | 12 #include "src/stub-cache.h" |
13 #include "src/type-info.h" | 13 #include "src/type-info.h" |
14 | 14 |
15 #include "src/ic-inl.h" | 15 #include "src/ic-inl.h" |
16 #include "src/objects-inl.h" | 16 #include "src/objects-inl.h" |
17 | 17 |
18 namespace v8 { | 18 namespace v8 { |
19 namespace internal { | 19 namespace internal { |
20 | 20 |
21 | 21 |
22 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, | 22 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, |
23 Handle<FixedArray> feedback_vector, | 23 Handle<FixedArray> feedback_vector, |
24 Handle<Context> native_context, | 24 Handle<Context> native_context, |
25 Zone* zone) | 25 Zone* zone) |
26 : native_context_(native_context), | 26 : native_context_(native_context), |
27 zone_(zone) { | 27 zone_(zone) { |
28 BuildDictionary(code); | 28 BuildDictionary(code); |
29 ASSERT(dictionary_->IsDictionary()); | 29 DCHECK(dictionary_->IsDictionary()); |
30 // We make a copy of the feedback vector because a GC could clear | 30 // We make a copy of the feedback vector because a GC could clear |
31 // the type feedback info contained therein. | 31 // the type feedback info contained therein. |
32 // TODO(mvstanton): revisit the decision to copy when we weakly | 32 // TODO(mvstanton): revisit the decision to copy when we weakly |
33 // traverse the feedback vector at GC time. | 33 // traverse the feedback vector at GC time. |
34 feedback_vector_ = isolate()->factory()->CopyFixedArray(feedback_vector); | 34 feedback_vector_ = isolate()->factory()->CopyFixedArray(feedback_vector); |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 static uint32_t IdToKey(TypeFeedbackId ast_id) { | 38 static uint32_t IdToKey(TypeFeedbackId ast_id) { |
39 return static_cast<uint32_t>(ast_id.ToInt()); | 39 return static_cast<uint32_t>(ast_id.ToInt()); |
40 } | 40 } |
41 | 41 |
42 | 42 |
43 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { | 43 Handle<Object> TypeFeedbackOracle::GetInfo(TypeFeedbackId ast_id) { |
44 int entry = dictionary_->FindEntry(IdToKey(ast_id)); | 44 int entry = dictionary_->FindEntry(IdToKey(ast_id)); |
45 if (entry != UnseededNumberDictionary::kNotFound) { | 45 if (entry != UnseededNumberDictionary::kNotFound) { |
46 Object* value = dictionary_->ValueAt(entry); | 46 Object* value = dictionary_->ValueAt(entry); |
47 if (value->IsCell()) { | 47 if (value->IsCell()) { |
48 Cell* cell = Cell::cast(value); | 48 Cell* cell = Cell::cast(value); |
49 return Handle<Object>(cell->value(), isolate()); | 49 return Handle<Object>(cell->value(), isolate()); |
50 } else { | 50 } else { |
51 return Handle<Object>(value, isolate()); | 51 return Handle<Object>(value, isolate()); |
52 } | 52 } |
53 } | 53 } |
54 return Handle<Object>::cast(isolate()->factory()->undefined_value()); | 54 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
55 } | 55 } |
56 | 56 |
57 | 57 |
58 Handle<Object> TypeFeedbackOracle::GetInfo(int slot) { | 58 Handle<Object> TypeFeedbackOracle::GetInfo(int slot) { |
59 ASSERT(slot >= 0 && slot < feedback_vector_->length()); | 59 DCHECK(slot >= 0 && slot < feedback_vector_->length()); |
60 Object* obj = feedback_vector_->get(slot); | 60 Object* obj = feedback_vector_->get(slot); |
61 if (!obj->IsJSFunction() || | 61 if (!obj->IsJSFunction() || |
62 !CanRetainOtherContext(JSFunction::cast(obj), *native_context_)) { | 62 !CanRetainOtherContext(JSFunction::cast(obj), *native_context_)) { |
63 return Handle<Object>(obj, isolate()); | 63 return Handle<Object>(obj, isolate()); |
64 } | 64 } |
65 return Handle<Object>::cast(isolate()->factory()->undefined_value()); | 65 return Handle<Object>::cast(isolate()->factory()->undefined_value()); |
66 } | 66 } |
67 | 67 |
68 | 68 |
69 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { | 69 bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 return Handle<JSFunction>::cast(info); | 139 return Handle<JSFunction>::cast(info); |
140 } | 140 } |
141 | 141 |
142 | 142 |
143 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(int slot) { | 143 Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(int slot) { |
144 Handle<Object> info = GetInfo(slot); | 144 Handle<Object> info = GetInfo(slot); |
145 if (FLAG_pretenuring_call_new || info->IsJSFunction()) { | 145 if (FLAG_pretenuring_call_new || info->IsJSFunction()) { |
146 return Handle<JSFunction>::cast(info); | 146 return Handle<JSFunction>::cast(info); |
147 } | 147 } |
148 | 148 |
149 ASSERT(info->IsAllocationSite()); | 149 DCHECK(info->IsAllocationSite()); |
150 return Handle<JSFunction>(isolate()->native_context()->array_function()); | 150 return Handle<JSFunction>(isolate()->native_context()->array_function()); |
151 } | 151 } |
152 | 152 |
153 | 153 |
154 Handle<AllocationSite> TypeFeedbackOracle::GetCallAllocationSite(int slot) { | 154 Handle<AllocationSite> TypeFeedbackOracle::GetCallAllocationSite(int slot) { |
155 Handle<Object> info = GetInfo(slot); | 155 Handle<Object> info = GetInfo(slot); |
156 if (info->IsAllocationSite()) { | 156 if (info->IsAllocationSite()) { |
157 return Handle<AllocationSite>::cast(info); | 157 return Handle<AllocationSite>::cast(info); |
158 } | 158 } |
159 return Handle<AllocationSite>::null(); | 159 return Handle<AllocationSite>::null(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 Type** left, | 211 Type** left, |
212 Type** right, | 212 Type** right, |
213 Type** result, | 213 Type** result, |
214 Maybe<int>* fixed_right_arg, | 214 Maybe<int>* fixed_right_arg, |
215 Handle<AllocationSite>* allocation_site, | 215 Handle<AllocationSite>* allocation_site, |
216 Token::Value op) { | 216 Token::Value op) { |
217 Handle<Object> object = GetInfo(id); | 217 Handle<Object> object = GetInfo(id); |
218 if (!object->IsCode()) { | 218 if (!object->IsCode()) { |
219 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the | 219 // For some binary ops we don't have ICs, e.g. Token::COMMA, but for the |
220 // operations covered by the BinaryOpIC we should always have them. | 220 // operations covered by the BinaryOpIC we should always have them. |
221 ASSERT(op < BinaryOpIC::State::FIRST_TOKEN || | 221 DCHECK(op < BinaryOpIC::State::FIRST_TOKEN || |
222 op > BinaryOpIC::State::LAST_TOKEN); | 222 op > BinaryOpIC::State::LAST_TOKEN); |
223 *left = *right = *result = Type::None(zone()); | 223 *left = *right = *result = Type::None(zone()); |
224 *fixed_right_arg = Maybe<int>(); | 224 *fixed_right_arg = Maybe<int>(); |
225 *allocation_site = Handle<AllocationSite>::null(); | 225 *allocation_site = Handle<AllocationSite>::null(); |
226 return; | 226 return; |
227 } | 227 } |
228 Handle<Code> code = Handle<Code>::cast(object); | 228 Handle<Code> code = Handle<Code>::cast(object); |
229 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 229 DCHECK_EQ(Code::BINARY_OP_IC, code->kind()); |
230 BinaryOpIC::State state(isolate(), code->extra_ic_state()); | 230 BinaryOpIC::State state(isolate(), code->extra_ic_state()); |
231 ASSERT_EQ(op, state.op()); | 231 DCHECK_EQ(op, state.op()); |
232 | 232 |
233 *left = state.GetLeftType(zone()); | 233 *left = state.GetLeftType(zone()); |
234 *right = state.GetRightType(zone()); | 234 *right = state.GetRightType(zone()); |
235 *result = state.GetResultType(zone()); | 235 *result = state.GetResultType(zone()); |
236 *fixed_right_arg = state.fixed_right_arg(); | 236 *fixed_right_arg = state.fixed_right_arg(); |
237 | 237 |
238 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); | 238 AllocationSite* first_allocation_site = code->FindFirstAllocationSite(); |
239 if (first_allocation_site != NULL) { | 239 if (first_allocation_site != NULL) { |
240 *allocation_site = handle(first_allocation_site); | 240 *allocation_site = handle(first_allocation_site); |
241 } else { | 241 } else { |
242 *allocation_site = Handle<AllocationSite>::null(); | 242 *allocation_site = Handle<AllocationSite>::null(); |
243 } | 243 } |
244 } | 244 } |
245 | 245 |
246 | 246 |
247 Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) { | 247 Type* TypeFeedbackOracle::CountType(TypeFeedbackId id) { |
248 Handle<Object> object = GetInfo(id); | 248 Handle<Object> object = GetInfo(id); |
249 if (!object->IsCode()) return Type::None(zone()); | 249 if (!object->IsCode()) return Type::None(zone()); |
250 Handle<Code> code = Handle<Code>::cast(object); | 250 Handle<Code> code = Handle<Code>::cast(object); |
251 ASSERT_EQ(Code::BINARY_OP_IC, code->kind()); | 251 DCHECK_EQ(Code::BINARY_OP_IC, code->kind()); |
252 BinaryOpIC::State state(isolate(), code->extra_ic_state()); | 252 BinaryOpIC::State state(isolate(), code->extra_ic_state()); |
253 return state.GetLeftType(zone()); | 253 return state.GetLeftType(zone()); |
254 } | 254 } |
255 | 255 |
256 | 256 |
257 void TypeFeedbackOracle::PropertyReceiverTypes(TypeFeedbackId id, | 257 void TypeFeedbackOracle::PropertyReceiverTypes(TypeFeedbackId id, |
258 Handle<String> name, | 258 Handle<String> name, |
259 SmallMapList* receiver_types) { | 259 SmallMapList* receiver_types) { |
260 receiver_types->Clear(); | 260 receiver_types->Clear(); |
261 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 261 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 } | 299 } |
300 | 300 |
301 | 301 |
302 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, | 302 void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, |
303 Handle<String> name, | 303 Handle<String> name, |
304 Code::Flags flags, | 304 Code::Flags flags, |
305 SmallMapList* types) { | 305 SmallMapList* types) { |
306 Handle<Object> object = GetInfo(ast_id); | 306 Handle<Object> object = GetInfo(ast_id); |
307 if (object->IsUndefined() || object->IsSmi()) return; | 307 if (object->IsUndefined() || object->IsSmi()) return; |
308 | 308 |
309 ASSERT(object->IsCode()); | 309 DCHECK(object->IsCode()); |
310 Handle<Code> code(Handle<Code>::cast(object)); | 310 Handle<Code> code(Handle<Code>::cast(object)); |
311 | 311 |
312 if (FLAG_collect_megamorphic_maps_from_stub_cache && | 312 if (FLAG_collect_megamorphic_maps_from_stub_cache && |
313 code->ic_state() == MEGAMORPHIC) { | 313 code->ic_state() == MEGAMORPHIC) { |
314 types->Reserve(4, zone()); | 314 types->Reserve(4, zone()); |
315 isolate()->stub_cache()->CollectMatchingMaps( | 315 isolate()->stub_cache()->CollectMatchingMaps( |
316 types, name, flags, native_context_, zone()); | 316 types, name, flags, native_context_, zone()); |
317 } else { | 317 } else { |
318 CollectReceiverTypes(ast_id, types); | 318 CollectReceiverTypes(ast_id, types); |
319 } | 319 } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 break; | 450 break; |
451 | 451 |
452 default: | 452 default: |
453 break; | 453 break; |
454 } | 454 } |
455 } | 455 } |
456 } | 456 } |
457 | 457 |
458 | 458 |
459 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { | 459 void TypeFeedbackOracle::SetInfo(TypeFeedbackId ast_id, Object* target) { |
460 ASSERT(dictionary_->FindEntry(IdToKey(ast_id)) == | 460 DCHECK(dictionary_->FindEntry(IdToKey(ast_id)) == |
461 UnseededNumberDictionary::kNotFound); | 461 UnseededNumberDictionary::kNotFound); |
462 // Dictionary has been allocated with sufficient size for all elements. | 462 // Dictionary has been allocated with sufficient size for all elements. |
463 DisallowHeapAllocation no_need_to_resize_dictionary; | 463 DisallowHeapAllocation no_need_to_resize_dictionary; |
464 HandleScope scope(isolate()); | 464 HandleScope scope(isolate()); |
465 USE(UnseededNumberDictionary::AtNumberPut( | 465 USE(UnseededNumberDictionary::AtNumberPut( |
466 dictionary_, IdToKey(ast_id), handle(target, isolate()))); | 466 dictionary_, IdToKey(ast_id), handle(target, isolate()))); |
467 } | 467 } |
468 | 468 |
469 | 469 |
470 } } // namespace v8::internal | 470 } } // namespace v8::internal |
OLD | NEW |