OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/object.h" | 5 #include "vm/object.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
11 #include "vm/bit_vector.h" | 11 #include "vm/bit_vector.h" |
12 #include "vm/bootstrap.h" | 12 #include "vm/bootstrap.h" |
13 #include "vm/class_finalizer.h" | 13 #include "vm/class_finalizer.h" |
14 #include "vm/code_observers.h" | 14 #include "vm/code_observers.h" |
15 #include "vm/compiler.h" | 15 #include "vm/compiler.h" |
16 #include "vm/compiler_stats.h" | 16 #include "vm/compiler_stats.h" |
17 #include "vm/dart.h" | 17 #include "vm/dart.h" |
18 #include "vm/dart_api_state.h" | 18 #include "vm/dart_api_state.h" |
19 #include "vm/dart_entry.h" | 19 #include "vm/dart_entry.h" |
20 #include "vm/datastream.h" | 20 #include "vm/datastream.h" |
21 #include "vm/debugger.h" | 21 #include "vm/debugger.h" |
22 #include "vm/deopt_instructions.h" | 22 #include "vm/deopt_instructions.h" |
23 #include "vm/disassembler.h" | 23 #include "vm/disassembler.h" |
24 #include "vm/double_conversion.h" | 24 #include "vm/double_conversion.h" |
25 #include "vm/exceptions.h" | 25 #include "vm/exceptions.h" |
26 #include "vm/growable_array.h" | 26 #include "vm/growable_array.h" |
27 #include "vm/hash_table.h" | 27 #include "vm/hash_table.h" |
28 #include "vm/heap.h" | 28 #include "vm/heap.h" |
29 #include "vm/intrinsifier.h" | 29 #include "vm/intrinsifier.h" |
| 30 #include "vm/isolate_reload.h" |
30 #include "vm/object_store.h" | 31 #include "vm/object_store.h" |
31 #include "vm/parser.h" | 32 #include "vm/parser.h" |
32 #include "vm/precompiler.h" | 33 #include "vm/precompiler.h" |
33 #include "vm/profiler.h" | 34 #include "vm/profiler.h" |
| 35 #include "vm/resolver.h" |
34 #include "vm/reusable_handles.h" | 36 #include "vm/reusable_handles.h" |
35 #include "vm/runtime_entry.h" | 37 #include "vm/runtime_entry.h" |
36 #include "vm/scopes.h" | 38 #include "vm/scopes.h" |
37 #include "vm/stack_frame.h" | 39 #include "vm/stack_frame.h" |
38 #include "vm/symbols.h" | 40 #include "vm/symbols.h" |
39 #include "vm/tags.h" | 41 #include "vm/tags.h" |
40 #include "vm/thread_registry.h" | 42 #include "vm/thread_registry.h" |
41 #include "vm/timeline.h" | 43 #include "vm/timeline.h" |
42 #include "vm/timer.h" | 44 #include "vm/timer.h" |
43 #include "vm/unicode.h" | 45 #include "vm/unicode.h" |
(...skipping 10 matching lines...) Expand all Loading... |
54 "When possible, partially or fully overlap the type arguments of a type " | 56 "When possible, partially or fully overlap the type arguments of a type " |
55 "with the type arguments of its super type."); | 57 "with the type arguments of its super type."); |
56 DEFINE_FLAG(bool, show_internal_names, false, | 58 DEFINE_FLAG(bool, show_internal_names, false, |
57 "Show names of internal classes (e.g. \"OneByteString\") in error messages " | 59 "Show names of internal classes (e.g. \"OneByteString\") in error messages " |
58 "instead of showing the corresponding interface names (e.g. \"String\")"); | 60 "instead of showing the corresponding interface names (e.g. \"String\")"); |
59 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache"); | 61 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache"); |
60 DEFINE_FLAG(bool, use_exp_cache, true, "Use library exported name cache"); | 62 DEFINE_FLAG(bool, use_exp_cache, true, "Use library exported name cache"); |
61 DEFINE_FLAG(bool, ignore_patch_signature_mismatch, false, | 63 DEFINE_FLAG(bool, ignore_patch_signature_mismatch, false, |
62 "Ignore patch file member signature mismatch."); | 64 "Ignore patch file member signature mismatch."); |
63 | 65 |
| 66 DEFINE_FLAG(bool, remove_script_timestamps_for_test, false, |
| 67 "Remove script timestamps to allow for deterministic testing."); |
| 68 |
64 DECLARE_FLAG(bool, show_invisible_frames); | 69 DECLARE_FLAG(bool, show_invisible_frames); |
65 DECLARE_FLAG(bool, trace_deoptimization); | 70 DECLARE_FLAG(bool, trace_deoptimization); |
66 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 71 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 72 DECLARE_FLAG(bool, trace_reload); |
67 DECLARE_FLAG(bool, write_protect_code); | 73 DECLARE_FLAG(bool, write_protect_code); |
68 DECLARE_FLAG(bool, support_externalizable_strings); | 74 DECLARE_FLAG(bool, support_externalizable_strings); |
69 | 75 |
70 | 76 |
71 static const char* const kGetterPrefix = "get:"; | 77 static const char* const kGetterPrefix = "get:"; |
72 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); | 78 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); |
73 static const char* const kSetterPrefix = "set:"; | 79 static const char* const kSetterPrefix = "set:"; |
74 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); | 80 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); |
75 | 81 |
76 // A cache of VM heap allocated preinitialized empty ic data entry arrays. | 82 // A cache of VM heap allocated preinitialized empty ic data entry arrays. |
(...skipping 2689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2766 DEBUG_ASSERT(IsMutatorOrAtSafepoint()); | 2772 DEBUG_ASSERT(IsMutatorOrAtSafepoint()); |
2767 ASSERT(code.is_optimized()); | 2773 ASSERT(code.is_optimized()); |
2768 CHACodeArray a(*this); | 2774 CHACodeArray a(*this); |
2769 a.Register(code); | 2775 a.Register(code); |
2770 } | 2776 } |
2771 | 2777 |
2772 | 2778 |
2773 void Class::DisableCHAOptimizedCode(const Class& subclass) { | 2779 void Class::DisableCHAOptimizedCode(const Class& subclass) { |
2774 ASSERT(Thread::Current()->IsMutatorThread()); | 2780 ASSERT(Thread::Current()->IsMutatorThread()); |
2775 CHACodeArray a(*this); | 2781 CHACodeArray a(*this); |
2776 if (FLAG_trace_deoptimization && a.HasCodes()) { | 2782 if (FLAG_trace_deoptimization && a.HasCodes() && !subclass.IsNull()) { |
2777 THR_Print("Adding subclass %s\n", subclass.ToCString()); | 2783 THR_Print("Adding subclass %s\n", subclass.ToCString()); |
2778 } | 2784 } |
2779 a.DisableCode(); | 2785 a.DisableCode(); |
2780 } | 2786 } |
2781 | 2787 |
2782 | 2788 |
| 2789 void Class::DisableAllCHAOptimizedCode() { |
| 2790 DisableCHAOptimizedCode(Class::Handle()); |
| 2791 } |
| 2792 |
| 2793 |
2783 bool Class::TraceAllocation(Isolate* isolate) const { | 2794 bool Class::TraceAllocation(Isolate* isolate) const { |
2784 ClassTable* class_table = isolate->class_table(); | 2795 ClassTable* class_table = isolate->class_table(); |
2785 return class_table->TraceAllocationFor(id()); | 2796 return class_table->TraceAllocationFor(id()); |
2786 } | 2797 } |
2787 | 2798 |
2788 | 2799 |
2789 void Class::SetTraceAllocation(bool trace_allocation) const { | 2800 void Class::SetTraceAllocation(bool trace_allocation) const { |
2790 Isolate* isolate = Isolate::Current(); | 2801 Isolate* isolate = Isolate::Current(); |
2791 const bool changed = trace_allocation != this->TraceAllocation(isolate); | 2802 const bool changed = trace_allocation != this->TraceAllocation(isolate); |
2792 if (changed) { | 2803 if (changed) { |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3117 const Array& new_arr = Array::Handle( | 3128 const Array& new_arr = Array::Handle( |
3118 Array::Grow(arr, num_old_fields + num_new_fields, Heap::kOld)); | 3129 Array::Grow(arr, num_old_fields + num_new_fields, Heap::kOld)); |
3119 for (intptr_t i = 0; i < num_new_fields; i++) { | 3130 for (intptr_t i = 0; i < num_new_fields; i++) { |
3120 new_arr.SetAt(i + num_old_fields, *new_fields.At(i)); | 3131 new_arr.SetAt(i + num_old_fields, *new_fields.At(i)); |
3121 } | 3132 } |
3122 SetFields(new_arr); | 3133 SetFields(new_arr); |
3123 } | 3134 } |
3124 | 3135 |
3125 | 3136 |
3126 template <class FakeInstance> | 3137 template <class FakeInstance> |
3127 RawClass* Class::New(intptr_t index) { | 3138 RawClass* Class::NewCommon(intptr_t index) { |
3128 ASSERT(Object::class_class() != Class::null()); | 3139 ASSERT(Object::class_class() != Class::null()); |
3129 Class& result = Class::Handle(); | 3140 Class& result = Class::Handle(); |
3130 { | 3141 { |
3131 RawObject* raw = Object::Allocate(Class::kClassId, | 3142 RawObject* raw = Object::Allocate(Class::kClassId, |
3132 Class::InstanceSize(), | 3143 Class::InstanceSize(), |
3133 Heap::kOld); | 3144 Heap::kOld); |
3134 NoSafepointScope no_safepoint; | 3145 NoSafepointScope no_safepoint; |
3135 result ^= raw; | 3146 result ^= raw; |
3136 } | 3147 } |
3137 FakeInstance fake; | 3148 FakeInstance fake; |
3138 ASSERT(fake.IsInstance()); | 3149 ASSERT(fake.IsInstance()); |
3139 result.set_handle_vtable(fake.vtable()); | 3150 result.set_handle_vtable(fake.vtable()); |
3140 result.set_instance_size(FakeInstance::InstanceSize()); | 3151 result.set_instance_size(FakeInstance::InstanceSize()); |
3141 result.set_next_field_offset(FakeInstance::NextFieldOffset()); | 3152 result.set_next_field_offset(FakeInstance::NextFieldOffset()); |
3142 result.set_id(index); | 3153 result.set_id(index); |
3143 result.set_state_bits(0); | 3154 result.set_state_bits(0); |
3144 result.set_type_arguments_field_offset_in_words(kNoTypeArguments); | 3155 result.set_type_arguments_field_offset_in_words(kNoTypeArguments); |
3145 result.set_num_type_arguments(kUnknownNumTypeArguments); | 3156 result.set_num_type_arguments(kUnknownNumTypeArguments); |
3146 result.set_num_own_type_arguments(kUnknownNumTypeArguments); | 3157 result.set_num_own_type_arguments(kUnknownNumTypeArguments); |
3147 result.set_num_native_fields(0); | 3158 result.set_num_native_fields(0); |
3148 result.set_token_pos(TokenPosition::kNoSource); | 3159 result.set_token_pos(TokenPosition::kNoSource); |
3149 result.InitEmptyFields(); | 3160 result.InitEmptyFields(); |
| 3161 return result.raw(); |
| 3162 } |
| 3163 |
| 3164 |
| 3165 template <class FakeInstance> |
| 3166 RawClass* Class::New(intptr_t index) { |
| 3167 Class& result = Class::Handle(NewCommon<FakeInstance>(index)); |
3150 Isolate::Current()->RegisterClass(result); | 3168 Isolate::Current()->RegisterClass(result); |
3151 return result.raw(); | 3169 return result.raw(); |
3152 } | 3170 } |
3153 | 3171 |
3154 | 3172 |
3155 RawClass* Class::New(const String& name, | 3173 RawClass* Class::New(const Library& lib, |
| 3174 const String& name, |
3156 const Script& script, | 3175 const Script& script, |
3157 TokenPosition token_pos) { | 3176 TokenPosition token_pos) { |
3158 Class& result = Class::Handle(New<Instance>(kIllegalCid)); | 3177 Class& result = Class::Handle(NewCommon<Instance>(kIllegalCid)); |
| 3178 result.set_library(lib); |
3159 result.set_name(name); | 3179 result.set_name(name); |
3160 result.set_script(script); | 3180 result.set_script(script); |
3161 result.set_token_pos(token_pos); | 3181 result.set_token_pos(token_pos); |
| 3182 Isolate::Current()->RegisterClass(result); |
3162 return result.raw(); | 3183 return result.raw(); |
3163 } | 3184 } |
3164 | 3185 |
3165 | 3186 |
3166 RawClass* Class::NewNativeWrapper(const Library& library, | 3187 RawClass* Class::NewNativeWrapper(const Library& library, |
3167 const String& name, | 3188 const String& name, |
3168 int field_count) { | 3189 int field_count) { |
3169 Class& cls = Class::Handle(library.LookupClass(name)); | 3190 Class& cls = Class::Handle(library.LookupClass(name)); |
3170 if (cls.IsNull()) { | 3191 if (cls.IsNull()) { |
3171 cls = New(name, Script::Handle(), TokenPosition::kNoSource); | 3192 cls = New(library, name, Script::Handle(), TokenPosition::kNoSource); |
3172 cls.SetFields(Object::empty_array()); | 3193 cls.SetFields(Object::empty_array()); |
3173 cls.SetFunctions(Object::empty_array()); | 3194 cls.SetFunctions(Object::empty_array()); |
3174 // Set super class to Object. | 3195 // Set super class to Object. |
3175 cls.set_super_type(Type::Handle(Type::ObjectType())); | 3196 cls.set_super_type(Type::Handle(Type::ObjectType())); |
3176 // Compute instance size. First word contains a pointer to a properly | 3197 // Compute instance size. First word contains a pointer to a properly |
3177 // sized typed array once the first native field has been set. | 3198 // sized typed array once the first native field has been set. |
3178 intptr_t instance_size = sizeof(RawInstance) + kWordSize; | 3199 intptr_t instance_size = sizeof(RawInstance) + kWordSize; |
3179 cls.set_instance_size(RoundedAllocationSize(instance_size)); | 3200 cls.set_instance_size(RoundedAllocationSize(instance_size)); |
3180 cls.set_next_field_offset(instance_size); | 3201 cls.set_next_field_offset(instance_size); |
3181 cls.set_num_native_fields(field_count); | 3202 cls.set_num_native_fields(field_count); |
(...skipping 2282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5464 | 5485 |
5465 | 5486 |
5466 void Function::ClearCode() const { | 5487 void Function::ClearCode() const { |
5467 ASSERT(Thread::Current()->IsMutatorThread()); | 5488 ASSERT(Thread::Current()->IsMutatorThread()); |
5468 ASSERT((usage_counter() != 0) || (ic_data_array() == Array::null())); | 5489 ASSERT((usage_counter() != 0) || (ic_data_array() == Array::null())); |
5469 StorePointer(&raw_ptr()->unoptimized_code_, Code::null()); | 5490 StorePointer(&raw_ptr()->unoptimized_code_, Code::null()); |
5470 SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); | 5491 SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); |
5471 } | 5492 } |
5472 | 5493 |
5473 | 5494 |
| 5495 void Function::EnsureHasCompiledUnoptimizedCode() const { |
| 5496 Thread* thread = Thread::Current(); |
| 5497 Zone* zone = thread->zone(); |
| 5498 ASSERT(thread->IsMutatorThread()); |
| 5499 |
| 5500 const Error& error = Error::Handle(zone, |
| 5501 Compiler::EnsureUnoptimizedCode(thread, *this)); |
| 5502 if (!error.IsNull()) { |
| 5503 Exceptions::PropagateError(error); |
| 5504 } |
| 5505 } |
| 5506 |
| 5507 |
5474 void Function::SwitchToUnoptimizedCode() const { | 5508 void Function::SwitchToUnoptimizedCode() const { |
5475 ASSERT(HasOptimizedCode()); | 5509 ASSERT(HasOptimizedCode()); |
5476 Thread* thread = Thread::Current(); | 5510 Thread* thread = Thread::Current(); |
5477 Isolate* isolate = thread->isolate(); | 5511 Isolate* isolate = thread->isolate(); |
5478 Zone* zone = thread->zone(); | 5512 Zone* zone = thread->zone(); |
5479 ASSERT(thread->IsMutatorThread()); | 5513 ASSERT(thread->IsMutatorThread()); |
5480 const Code& current_code = Code::Handle(zone, CurrentCode()); | 5514 const Code& current_code = Code::Handle(zone, CurrentCode()); |
5481 | 5515 |
5482 if (FLAG_trace_deoptimization_verbose) { | 5516 if (FLAG_trace_deoptimization_verbose) { |
5483 THR_Print("Disabling optimized code: '%s' entry: %#" Px "\n", | 5517 THR_Print("Disabling optimized code: '%s' entry: %#" Px "\n", |
5484 ToFullyQualifiedCString(), | 5518 ToFullyQualifiedCString(), |
5485 current_code.EntryPoint()); | 5519 current_code.EntryPoint()); |
5486 } | 5520 } |
5487 current_code.DisableDartCode(); | 5521 current_code.DisableDartCode(); |
5488 const Error& error = Error::Handle(zone, | 5522 const Error& error = Error::Handle(zone, |
5489 Compiler::EnsureUnoptimizedCode(thread, *this)); | 5523 Compiler::EnsureUnoptimizedCode(thread, *this)); |
5490 if (!error.IsNull()) { | 5524 if (!error.IsNull()) { |
5491 Exceptions::PropagateError(error); | 5525 Exceptions::PropagateError(error); |
5492 } | 5526 } |
5493 const Code& unopt_code = Code::Handle(zone, unoptimized_code()); | 5527 const Code& unopt_code = Code::Handle(zone, unoptimized_code()); |
5494 AttachCode(unopt_code); | 5528 AttachCode(unopt_code); |
5495 unopt_code.Enable(); | 5529 unopt_code.Enable(); |
5496 isolate->TrackDeoptimizedCode(current_code); | 5530 isolate->TrackDeoptimizedCode(current_code); |
5497 } | 5531 } |
5498 | 5532 |
5499 | 5533 |
| 5534 void Function::SwitchToLazyCompiledUnoptimizedCode() const { |
| 5535 if (!HasOptimizedCode()) { |
| 5536 return; |
| 5537 } |
| 5538 |
| 5539 Thread* thread = Thread::Current(); |
| 5540 Zone* zone = thread->zone(); |
| 5541 ASSERT(thread->IsMutatorThread()); |
| 5542 |
| 5543 const Code& current_code = Code::Handle(zone, CurrentCode()); |
| 5544 TIR_Print("Disabling optimized code for %s\n", ToCString()); |
| 5545 current_code.DisableDartCode(); |
| 5546 |
| 5547 const Code& unopt_code = Code::Handle(zone, unoptimized_code()); |
| 5548 if (unopt_code.IsNull()) { |
| 5549 // Set the lazy compile code. |
| 5550 TIR_Print("Switched to lazy compile stub for %s\n", ToCString()); |
| 5551 SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); |
| 5552 return; |
| 5553 } |
| 5554 |
| 5555 TIR_Print("Switched to unoptimized code for %s\n", ToCString()); |
| 5556 |
| 5557 AttachCode(unopt_code); |
| 5558 unopt_code.Enable(); |
| 5559 } |
| 5560 |
| 5561 |
5500 void Function::set_unoptimized_code(const Code& value) const { | 5562 void Function::set_unoptimized_code(const Code& value) const { |
5501 ASSERT(Thread::Current()->IsMutatorThread()); | 5563 ASSERT(Thread::Current()->IsMutatorThread()); |
5502 ASSERT(value.IsNull() || !value.is_optimized()); | 5564 ASSERT(value.IsNull() || !value.is_optimized()); |
5503 StorePointer(&raw_ptr()->unoptimized_code_, value.raw()); | 5565 StorePointer(&raw_ptr()->unoptimized_code_, value.raw()); |
5504 } | 5566 } |
5505 | 5567 |
5506 | 5568 |
5507 RawContextScope* Function::context_scope() const { | 5569 RawContextScope* Function::context_scope() const { |
5508 if (IsClosureFunction()) { | 5570 if (IsClosureFunction()) { |
5509 const Object& obj = Object::Handle(raw_ptr()->data_); | 5571 const Object& obj = Object::Handle(raw_ptr()->data_); |
(...skipping 1544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7054 if (raw_ptr()->owner_->IsClass()) { | 7116 if (raw_ptr()->owner_->IsClass()) { |
7055 return Class::RawCast(raw_ptr()->owner_); | 7117 return Class::RawCast(raw_ptr()->owner_); |
7056 } | 7118 } |
7057 const Object& obj = Object::Handle(raw_ptr()->owner_); | 7119 const Object& obj = Object::Handle(raw_ptr()->owner_); |
7058 ASSERT(obj.IsPatchClass()); | 7120 ASSERT(obj.IsPatchClass()); |
7059 return PatchClass::Cast(obj).origin_class(); | 7121 return PatchClass::Cast(obj).origin_class(); |
7060 } | 7122 } |
7061 | 7123 |
7062 | 7124 |
7063 RawScript* Function::script() const { | 7125 RawScript* Function::script() const { |
| 7126 // NOTE(turnidge): If you update this function, you probably want to |
| 7127 // update Class::PatchFieldsAndFunctions() at the same time. |
7064 if (token_pos() == TokenPosition::kMinSource) { | 7128 if (token_pos() == TokenPosition::kMinSource) { |
7065 // Testing for position 0 is an optimization that relies on temporary | 7129 // Testing for position 0 is an optimization that relies on temporary |
7066 // eval functions having token position 0. | 7130 // eval functions having token position 0. |
7067 const Script& script = Script::Handle(eval_script()); | 7131 const Script& script = Script::Handle(eval_script()); |
7068 if (!script.IsNull()) { | 7132 if (!script.IsNull()) { |
7069 return script.raw(); | 7133 return script.raw(); |
7070 } | 7134 } |
7071 } | 7135 } |
7072 if (IsClosureFunction()) { | 7136 if (IsClosureFunction()) { |
7073 return Function::Handle(parent_function()).script(); | 7137 return Function::Handle(parent_function()).script(); |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7531 const Object& obj = Object::Handle(field.raw_ptr()->owner_); | 7595 const Object& obj = Object::Handle(field.raw_ptr()->owner_); |
7532 if (obj.IsClass()) { | 7596 if (obj.IsClass()) { |
7533 return Class::Cast(obj).raw(); | 7597 return Class::Cast(obj).raw(); |
7534 } | 7598 } |
7535 ASSERT(obj.IsPatchClass()); | 7599 ASSERT(obj.IsPatchClass()); |
7536 return PatchClass::Cast(obj).origin_class(); | 7600 return PatchClass::Cast(obj).origin_class(); |
7537 } | 7601 } |
7538 | 7602 |
7539 | 7603 |
7540 RawScript* Field::Script() const { | 7604 RawScript* Field::Script() const { |
| 7605 // NOTE(turnidge): If you update this function, you probably want to |
| 7606 // update Class::PatchFieldsAndFunctions() at the same time. |
7541 const Field& field = Field::Handle(Original()); | 7607 const Field& field = Field::Handle(Original()); |
7542 ASSERT(field.IsOriginal()); | 7608 ASSERT(field.IsOriginal()); |
7543 const Object& obj = Object::Handle(field.raw_ptr()->owner_); | 7609 const Object& obj = Object::Handle(field.raw_ptr()->owner_); |
7544 if (obj.IsClass()) { | 7610 if (obj.IsClass()) { |
7545 return Class::Cast(obj).script(); | 7611 return Class::Cast(obj).script(); |
7546 } | 7612 } |
7547 ASSERT(obj.IsPatchClass()); | 7613 ASSERT(obj.IsPatchClass()); |
7548 return PatchClass::Cast(obj).script(); | 7614 return PatchClass::Cast(obj).script(); |
7549 } | 7615 } |
7550 | 7616 |
(...skipping 11 matching lines...) Expand all Loading... |
7562 | 7628 |
7563 RawField* Field::New() { | 7629 RawField* Field::New() { |
7564 ASSERT(Object::field_class() != Class::null()); | 7630 ASSERT(Object::field_class() != Class::null()); |
7565 RawObject* raw = Object::Allocate(Field::kClassId, | 7631 RawObject* raw = Object::Allocate(Field::kClassId, |
7566 Field::InstanceSize(), | 7632 Field::InstanceSize(), |
7567 Heap::kOld); | 7633 Heap::kOld); |
7568 return reinterpret_cast<RawField*>(raw); | 7634 return reinterpret_cast<RawField*>(raw); |
7569 } | 7635 } |
7570 | 7636 |
7571 | 7637 |
7572 RawField* Field::New(const String& name, | 7638 void Field::InitializeNew(const Field& result, |
7573 bool is_static, | 7639 const String& name, |
7574 bool is_final, | 7640 bool is_static, |
7575 bool is_const, | 7641 bool is_final, |
7576 bool is_reflectable, | 7642 bool is_const, |
7577 const Class& owner, | 7643 bool is_reflectable, |
7578 const AbstractType& type, | 7644 const Object& owner, |
7579 TokenPosition token_pos) { | 7645 TokenPosition token_pos) { |
7580 ASSERT(!owner.IsNull()); | |
7581 const Field& result = Field::Handle(Field::New()); | |
7582 result.set_name(name); | 7646 result.set_name(name); |
7583 result.set_is_static(is_static); | 7647 result.set_is_static(is_static); |
7584 if (!is_static) { | 7648 if (!is_static) { |
7585 result.SetOffset(0); | 7649 result.SetOffset(0); |
7586 } | 7650 } |
7587 result.set_is_final(is_final); | 7651 result.set_is_final(is_final); |
7588 result.set_is_const(is_const); | 7652 result.set_is_const(is_const); |
7589 result.set_is_reflectable(is_reflectable); | 7653 result.set_is_reflectable(is_reflectable); |
7590 result.set_is_double_initialized(false); | 7654 result.set_is_double_initialized(false); |
7591 result.set_owner(owner); | 7655 result.set_owner(owner); |
7592 result.SetFieldType(type); | |
7593 result.set_token_pos(token_pos); | 7656 result.set_token_pos(token_pos); |
7594 result.set_has_initializer(false); | 7657 result.set_has_initializer(false); |
7595 result.set_is_unboxing_candidate(true); | 7658 result.set_is_unboxing_candidate(true); |
7596 result.set_guarded_cid(FLAG_use_field_guards ? kIllegalCid : kDynamicCid); | 7659 Isolate* isolate = Isolate::Current(); |
7597 result.set_is_nullable(FLAG_use_field_guards ? false : true); | 7660 |
| 7661 // Use field guards if they are enabled and the isolate has never reloaded. |
| 7662 // TODO(johnmccutchan): The reload case assumes the worst case (everything is |
| 7663 // dynamic and possibly null). Attempt to relax this later. |
| 7664 const bool use_field_guards = |
| 7665 FLAG_use_field_guards && !isolate->HasAttemptedReload(); |
| 7666 result.set_guarded_cid(use_field_guards ? kIllegalCid : kDynamicCid); |
| 7667 result.set_is_nullable(use_field_guards ? false : true); |
7598 result.set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset); | 7668 result.set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset); |
7599 // Presently, we only attempt to remember the list length for final fields. | 7669 // Presently, we only attempt to remember the list length for final fields. |
7600 if (is_final && FLAG_use_field_guards) { | 7670 if (is_final && use_field_guards) { |
7601 result.set_guarded_list_length(Field::kUnknownFixedLength); | 7671 result.set_guarded_list_length(Field::kUnknownFixedLength); |
7602 } else { | 7672 } else { |
7603 result.set_guarded_list_length(Field::kNoFixedLength); | 7673 result.set_guarded_list_length(Field::kNoFixedLength); |
7604 } | 7674 } |
| 7675 } |
| 7676 |
| 7677 |
| 7678 RawField* Field::New(const String& name, |
| 7679 bool is_static, |
| 7680 bool is_final, |
| 7681 bool is_const, |
| 7682 bool is_reflectable, |
| 7683 const Class& owner, |
| 7684 const AbstractType& type, |
| 7685 TokenPosition token_pos) { |
| 7686 ASSERT(!owner.IsNull()); |
| 7687 const Field& result = Field::Handle(Field::New()); |
| 7688 InitializeNew(result, |
| 7689 name, |
| 7690 is_static, |
| 7691 is_final, |
| 7692 is_const, |
| 7693 is_reflectable, |
| 7694 owner, |
| 7695 token_pos); |
| 7696 result.SetFieldType(type); |
7605 return result.raw(); | 7697 return result.raw(); |
7606 } | 7698 } |
7607 | 7699 |
7608 | 7700 |
7609 RawField* Field::NewTopLevel(const String& name, | 7701 RawField* Field::NewTopLevel(const String& name, |
7610 bool is_final, | 7702 bool is_final, |
7611 bool is_const, | 7703 bool is_const, |
7612 const Object& owner, | 7704 const Object& owner, |
7613 TokenPosition token_pos) { | 7705 TokenPosition token_pos) { |
7614 ASSERT(!owner.IsNull()); | 7706 ASSERT(!owner.IsNull()); |
7615 const Field& result = Field::Handle(Field::New()); | 7707 const Field& result = Field::Handle(Field::New()); |
7616 result.set_name(name); | 7708 InitializeNew(result, |
7617 result.set_is_static(true); | 7709 name, |
7618 result.set_is_final(is_final); | 7710 true, /* is_static */ |
7619 result.set_is_const(is_const); | 7711 is_final, |
7620 result.set_is_reflectable(true); | 7712 is_const, |
7621 result.set_is_double_initialized(false); | 7713 true, /* is_reflectable */ |
7622 result.set_owner(owner); | 7714 owner, |
7623 result.set_token_pos(token_pos); | 7715 token_pos); |
7624 result.set_has_initializer(false); | |
7625 result.set_is_unboxing_candidate(true); | |
7626 result.set_guarded_cid(FLAG_use_field_guards ? kIllegalCid : kDynamicCid); | |
7627 result.set_is_nullable(FLAG_use_field_guards ? false : true); | |
7628 result.set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset); | |
7629 // Presently, we only attempt to remember the list length for final fields. | |
7630 if (is_final && FLAG_use_field_guards) { | |
7631 result.set_guarded_list_length(Field::kUnknownFixedLength); | |
7632 } else { | |
7633 result.set_guarded_list_length(Field::kNoFixedLength); | |
7634 } | |
7635 return result.raw(); | 7716 return result.raw(); |
7636 } | 7717 } |
7637 | 7718 |
7638 | 7719 |
7639 RawField* Field::Clone(const Class& new_owner) const { | 7720 RawField* Field::Clone(const Class& new_owner) const { |
7640 Field& clone = Field::Handle(); | 7721 Field& clone = Field::Handle(); |
7641 clone ^= Object::Clone(*this, Heap::kOld); | 7722 clone ^= Object::Clone(*this, Heap::kOld); |
7642 const Class& owner = Class::Handle(this->Owner()); | 7723 const Class& owner = Class::Handle(this->Owner()); |
7643 const PatchClass& clone_owner = | 7724 const PatchClass& clone_owner = |
7644 PatchClass::Handle(PatchClass::New(new_owner, owner)); | 7725 PatchClass::Handle(PatchClass::New(new_owner, owner)); |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8093 if (UpdateGuardedCidAndLength(value)) { | 8174 if (UpdateGuardedCidAndLength(value)) { |
8094 if (FLAG_trace_field_guards) { | 8175 if (FLAG_trace_field_guards) { |
8095 THR_Print(" => %s\n", GuardedPropertiesAsCString()); | 8176 THR_Print(" => %s\n", GuardedPropertiesAsCString()); |
8096 } | 8177 } |
8097 | 8178 |
8098 DeoptimizeDependentCode(); | 8179 DeoptimizeDependentCode(); |
8099 } | 8180 } |
8100 } | 8181 } |
8101 | 8182 |
8102 | 8183 |
| 8184 void Field::ForceDynamicGuardedCidAndLength() const { |
| 8185 // Assume nothing about this field. |
| 8186 set_is_unboxing_candidate(false); |
| 8187 set_guarded_cid(kDynamicCid); |
| 8188 set_is_nullable(true); |
| 8189 set_guarded_list_length(Field::kNoFixedLength); |
| 8190 set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset); |
| 8191 // Drop any code that relied on the above assumptions. |
| 8192 DeoptimizeDependentCode(); |
| 8193 } |
| 8194 |
| 8195 |
8103 void LiteralToken::set_literal(const String& literal) const { | 8196 void LiteralToken::set_literal(const String& literal) const { |
8104 StorePointer(&raw_ptr()->literal_, literal.raw()); | 8197 StorePointer(&raw_ptr()->literal_, literal.raw()); |
8105 } | 8198 } |
8106 | 8199 |
8107 | 8200 |
8108 void LiteralToken::set_value(const Object& value) const { | 8201 void LiteralToken::set_value(const Object& value) const { |
8109 StorePointer(&raw_ptr()->value_, value.raw()); | 8202 StorePointer(&raw_ptr()->value_, value.raw()); |
8110 } | 8203 } |
8111 | 8204 |
8112 | 8205 |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8917 void Script::set_source(const String& value) const { | 9010 void Script::set_source(const String& value) const { |
8918 StorePointer(&raw_ptr()->source_, value.raw()); | 9011 StorePointer(&raw_ptr()->source_, value.raw()); |
8919 } | 9012 } |
8920 | 9013 |
8921 | 9014 |
8922 void Script::set_kind(RawScript::Kind value) const { | 9015 void Script::set_kind(RawScript::Kind value) const { |
8923 StoreNonPointer(&raw_ptr()->kind_, value); | 9016 StoreNonPointer(&raw_ptr()->kind_, value); |
8924 } | 9017 } |
8925 | 9018 |
8926 | 9019 |
| 9020 void Script::set_load_timestamp(int64_t value) const { |
| 9021 StoreNonPointer(&raw_ptr()->load_timestamp_, value); |
| 9022 } |
| 9023 |
| 9024 |
8927 void Script::set_tokens(const TokenStream& value) const { | 9025 void Script::set_tokens(const TokenStream& value) const { |
8928 StorePointer(&raw_ptr()->tokens_, value.raw()); | 9026 StorePointer(&raw_ptr()->tokens_, value.raw()); |
8929 } | 9027 } |
8930 | 9028 |
8931 | 9029 |
8932 void Script::Tokenize(const String& private_key, | 9030 void Script::Tokenize(const String& private_key, |
8933 bool use_shared_tokens) const { | 9031 bool use_shared_tokens) const { |
8934 Thread* thread = Thread::Current(); | 9032 Thread* thread = Thread::Current(); |
8935 Zone* zone = thread->zone(); | 9033 Zone* zone = thread->zone(); |
8936 const TokenStream& tkns = TokenStream::Handle(zone, tokens()); | 9034 const TokenStream& tkns = TokenStream::Handle(zone, tokens()); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9172 | 9270 |
9173 RawScript* Script::New(const String& url, | 9271 RawScript* Script::New(const String& url, |
9174 const String& source, | 9272 const String& source, |
9175 RawScript::Kind kind) { | 9273 RawScript::Kind kind) { |
9176 Thread* thread = Thread::Current(); | 9274 Thread* thread = Thread::Current(); |
9177 Zone* zone = thread->zone(); | 9275 Zone* zone = thread->zone(); |
9178 const Script& result = Script::Handle(zone, Script::New()); | 9276 const Script& result = Script::Handle(zone, Script::New()); |
9179 result.set_url(String::Handle(zone, Symbols::New(thread, url))); | 9277 result.set_url(String::Handle(zone, Symbols::New(thread, url))); |
9180 result.set_source(source); | 9278 result.set_source(source); |
9181 result.set_kind(kind); | 9279 result.set_kind(kind); |
| 9280 result.set_load_timestamp(FLAG_remove_script_timestamps_for_test |
| 9281 ? 0 : OS::GetCurrentTimeMillis()); |
9182 result.SetLocationOffset(0, 0); | 9282 result.SetLocationOffset(0, 0); |
9183 return result.raw(); | 9283 return result.raw(); |
9184 } | 9284 } |
9185 | 9285 |
9186 | 9286 |
9187 const char* Script::ToCString() const { | 9287 const char* Script::ToCString() const { |
9188 return "Script"; | 9288 const String& name = String::Handle(url()); |
| 9289 return OS::SCreate(Thread::Current()->zone(), "Script(%s)", name.ToCString()); |
9189 } | 9290 } |
9190 | 9291 |
9191 | 9292 |
9192 RawLibrary* Script::FindLibrary() const { | 9293 RawLibrary* Script::FindLibrary() const { |
9193 Thread* thread = Thread::Current(); | 9294 Thread* thread = Thread::Current(); |
9194 Zone* zone = thread->zone(); | 9295 Zone* zone = thread->zone(); |
9195 Isolate* isolate = thread->isolate(); | 9296 Isolate* isolate = thread->isolate(); |
9196 const GrowableObjectArray& libs = GrowableObjectArray::Handle(zone, | 9297 const GrowableObjectArray& libs = GrowableObjectArray::Handle(zone, |
9197 isolate->object_store()->libraries()); | 9298 isolate->object_store()->libraries()); |
9198 Library& lib = Library::Handle(zone); | 9299 Library& lib = Library::Handle(zone); |
(...skipping 3466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12665 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { | 12766 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { |
12666 return num_args + 1 /* target function*/ + 1 /* frequency */; | 12767 return num_args + 1 /* target function*/ + 1 /* frequency */; |
12667 } | 12768 } |
12668 | 12769 |
12669 | 12770 |
12670 intptr_t ICData::TestEntryLength() const { | 12771 intptr_t ICData::TestEntryLength() const { |
12671 return TestEntryLengthFor(NumArgsTested()); | 12772 return TestEntryLengthFor(NumArgsTested()); |
12672 } | 12773 } |
12673 | 12774 |
12674 | 12775 |
| 12776 intptr_t ICData::Length() const { |
| 12777 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()); |
| 12778 } |
| 12779 |
| 12780 |
12675 intptr_t ICData::NumberOfChecks() const { | 12781 intptr_t ICData::NumberOfChecks() const { |
12676 // Do not count the sentinel; | 12782 const intptr_t length = Length(); |
12677 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; | 12783 for (intptr_t i = 0; i < length; i++) { |
| 12784 if (IsSentinelAt(i)) { |
| 12785 return i; |
| 12786 } |
| 12787 } |
| 12788 UNREACHABLE(); |
| 12789 return -1; |
12678 } | 12790 } |
12679 | 12791 |
12680 | 12792 |
12681 // Discounts any checks with usage of zero. | 12793 // Discounts any checks with usage of zero. |
12682 intptr_t ICData::NumberOfUsedChecks() const { | 12794 intptr_t ICData::NumberOfUsedChecks() const { |
12683 intptr_t n = NumberOfChecks(); | 12795 intptr_t n = NumberOfChecks(); |
12684 if (n == 0) { | 12796 if (n == 0) { |
12685 return 0; | 12797 return 0; |
12686 } | 12798 } |
12687 intptr_t count = 0; | 12799 intptr_t count = 0; |
(...skipping 16 matching lines...) Expand all Loading... |
12704 | 12816 |
12705 #if defined(DEBUG) | 12817 #if defined(DEBUG) |
12706 // Used in asserts to verify that a check is not added twice. | 12818 // Used in asserts to verify that a check is not added twice. |
12707 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { | 12819 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { |
12708 const intptr_t len = NumberOfChecks(); | 12820 const intptr_t len = NumberOfChecks(); |
12709 for (intptr_t i = 0; i < len; i++) { | 12821 for (intptr_t i = 0; i < len; i++) { |
12710 GrowableArray<intptr_t> class_ids; | 12822 GrowableArray<intptr_t> class_ids; |
12711 GetClassIdsAt(i, &class_ids); | 12823 GetClassIdsAt(i, &class_ids); |
12712 bool matches = true; | 12824 bool matches = true; |
12713 for (intptr_t k = 0; k < class_ids.length(); k++) { | 12825 for (intptr_t k = 0; k < class_ids.length(); k++) { |
| 12826 ASSERT(class_ids[k] != kIllegalCid); |
12714 if (class_ids[k] != cids[k]) { | 12827 if (class_ids[k] != cids[k]) { |
12715 matches = false; | 12828 matches = false; |
12716 break; | 12829 break; |
12717 } | 12830 } |
12718 } | 12831 } |
12719 if (matches) { | 12832 if (matches) { |
12720 return true; | 12833 return true; |
12721 } | 12834 } |
12722 } | 12835 } |
12723 return false; | 12836 return false; |
12724 } | 12837 } |
12725 #endif // DEBUG | 12838 #endif // DEBUG |
12726 | 12839 |
12727 | 12840 |
| 12841 void ICData::WriteSentinelAt(intptr_t index) const { |
| 12842 const intptr_t len = Length(); |
| 12843 ASSERT(index >= 0); |
| 12844 ASSERT(index < len); |
| 12845 Array& data = Array::Handle(ic_data()); |
| 12846 const intptr_t start = index * TestEntryLength(); |
| 12847 const intptr_t end = start + TestEntryLength(); |
| 12848 for (intptr_t i = start; i < end; i++) { |
| 12849 data.SetAt(i, smi_illegal_cid()); |
| 12850 } |
| 12851 } |
| 12852 |
| 12853 |
| 12854 void ICData::ClearCountAt(intptr_t index) const { |
| 12855 const intptr_t len = NumberOfChecks(); |
| 12856 ASSERT(index >= 0); |
| 12857 ASSERT(index < len); |
| 12858 SetCountAt(index, 0); |
| 12859 } |
| 12860 |
| 12861 |
| 12862 void ICData::ClearWithSentinel() const { |
| 12863 if (IsImmutable()) { |
| 12864 return; |
| 12865 } |
| 12866 // Write the sentinel value into all entries except the first one. |
| 12867 const intptr_t len = Length(); |
| 12868 if (len == 0) { |
| 12869 return; |
| 12870 } |
| 12871 // The final entry is always the sentinel. |
| 12872 ASSERT(IsSentinelAt(len - 1)); |
| 12873 for (intptr_t i = len - 1; i > 0; i--) { |
| 12874 WriteSentinelAt(i); |
| 12875 } |
| 12876 if (NumArgsTested() != 2) { |
| 12877 // Not the smi fast path case, write sentinel to first one and exit. |
| 12878 WriteSentinelAt(0); |
| 12879 return; |
| 12880 } |
| 12881 if (IsSentinelAt(0)) { |
| 12882 return; |
| 12883 } |
| 12884 Zone* zone = Thread::Current()->zone(); |
| 12885 const String& name = String::Handle(target_name()); |
| 12886 const Class& smi_class = Class::Handle(Smi::Class()); |
| 12887 const Function& smi_op_target = |
| 12888 Function::Handle(Resolver::ResolveDynamicAnyArgs(zone, smi_class, name)); |
| 12889 GrowableArray<intptr_t> class_ids(2); |
| 12890 Function& target = Function::Handle(); |
| 12891 GetCheckAt(0, &class_ids, &target); |
| 12892 if ((target.raw() == smi_op_target.raw()) && |
| 12893 (class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 12894 // The smi fast path case, preserve the initial entry but reset the count. |
| 12895 ClearCountAt(0); |
| 12896 return; |
| 12897 } |
| 12898 WriteSentinelAt(0); |
| 12899 } |
| 12900 |
| 12901 |
| 12902 void ICData::ClearAndSetStaticTarget(const Function& func) const { |
| 12903 if (IsImmutable()) { |
| 12904 return; |
| 12905 } |
| 12906 const intptr_t len = Length(); |
| 12907 if (len == 0) { |
| 12908 return; |
| 12909 } |
| 12910 // The final entry is always the sentinel. |
| 12911 ASSERT(IsSentinelAt(len - 1)); |
| 12912 if (NumArgsTested() == 0) { |
| 12913 // No type feedback is being collected. |
| 12914 const Array& data = Array::Handle(ic_data()); |
| 12915 // Static calls with no argument checks hold only one target and the |
| 12916 // sentinel value. |
| 12917 ASSERT(len == 2); |
| 12918 // Static calls with no argument checks only need two words. |
| 12919 ASSERT(TestEntryLength() == 2); |
| 12920 // Set the target. |
| 12921 data.SetAt(0, func); |
| 12922 // Set count to 0 as this is called during compilation, before the |
| 12923 // call has been executed. |
| 12924 const Smi& value = Smi::Handle(Smi::New(0)); |
| 12925 data.SetAt(1, value); |
| 12926 } else { |
| 12927 // Type feedback on arguments is being collected. |
| 12928 const Array& data = Array::Handle(ic_data()); |
| 12929 |
| 12930 // Fill all but the first entry with the sentinel. |
| 12931 for (intptr_t i = len - 1; i > 0; i--) { |
| 12932 WriteSentinelAt(i); |
| 12933 } |
| 12934 // Rewrite the dummy entry. |
| 12935 const Smi& object_cid = Smi::Handle(Smi::New(kObjectCid)); |
| 12936 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
| 12937 data.SetAt(i, object_cid); |
| 12938 } |
| 12939 data.SetAt(NumArgsTested(), func); |
| 12940 const Smi& value = Smi::Handle(Smi::New(0)); |
| 12941 data.SetAt(NumArgsTested() + 1, value); |
| 12942 } |
| 12943 } |
| 12944 |
| 12945 |
| 12946 // Add an initial Smi/Smi check with count 0. |
| 12947 bool ICData::AddSmiSmiCheckForFastSmiStubs() const { |
| 12948 bool is_smi_two_args_op = false; |
| 12949 |
| 12950 ASSERT(NumArgsTested() == 2); |
| 12951 const String& name = String::Handle(target_name()); |
| 12952 const Class& smi_class = Class::Handle(Smi::Class()); |
| 12953 Zone* zone = Thread::Current()->zone(); |
| 12954 const Function& smi_op_target = |
| 12955 Function::Handle(Resolver::ResolveDynamicAnyArgs(zone, smi_class, name)); |
| 12956 if (NumberOfChecks() == 0) { |
| 12957 GrowableArray<intptr_t> class_ids(2); |
| 12958 class_ids.Add(kSmiCid); |
| 12959 class_ids.Add(kSmiCid); |
| 12960 AddCheck(class_ids, smi_op_target); |
| 12961 // 'AddCheck' sets the initial count to 1. |
| 12962 SetCountAt(0, 0); |
| 12963 is_smi_two_args_op = true; |
| 12964 } else if (NumberOfChecks() == 1) { |
| 12965 GrowableArray<intptr_t> class_ids(2); |
| 12966 Function& target = Function::Handle(); |
| 12967 GetCheckAt(0, &class_ids, &target); |
| 12968 if ((target.raw() == smi_op_target.raw()) && |
| 12969 (class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 12970 is_smi_two_args_op = true; |
| 12971 } |
| 12972 } |
| 12973 return is_smi_two_args_op; |
| 12974 } |
| 12975 |
| 12976 |
12728 // Used for unoptimized static calls when no class-ids are checked. | 12977 // Used for unoptimized static calls when no class-ids are checked. |
12729 void ICData::AddTarget(const Function& target) const { | 12978 void ICData::AddTarget(const Function& target) const { |
12730 ASSERT(!target.IsNull()); | 12979 ASSERT(!target.IsNull()); |
12731 if (NumArgsTested() > 0) { | 12980 if (NumArgsTested() > 0) { |
12732 // Create a fake cid entry, so that we can store the target. | 12981 // Create a fake cid entry, so that we can store the target. |
12733 if (NumArgsTested() == 1) { | 12982 if (NumArgsTested() == 1) { |
12734 AddReceiverCheck(kObjectCid, target, 1); | 12983 AddReceiverCheck(kObjectCid, target, 1); |
12735 } else { | 12984 } else { |
12736 GrowableArray<intptr_t> class_ids(NumArgsTested()); | 12985 GrowableArray<intptr_t> class_ids(NumArgsTested()); |
12737 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 12986 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12787 // Replace dummy entry. | 13036 // Replace dummy entry. |
12788 Smi& value = Smi::Handle(); | 13037 Smi& value = Smi::Handle(); |
12789 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 13038 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
12790 ASSERT(class_ids[i] != kIllegalCid); | 13039 ASSERT(class_ids[i] != kIllegalCid); |
12791 value = Smi::New(class_ids[i]); | 13040 value = Smi::New(class_ids[i]); |
12792 data.SetAt(i, value); | 13041 data.SetAt(i, value); |
12793 } | 13042 } |
12794 return; | 13043 return; |
12795 } | 13044 } |
12796 } | 13045 } |
12797 const intptr_t new_len = data.Length() + TestEntryLength(); | 13046 intptr_t index = -1; |
12798 data = Array::Grow(data, new_len, Heap::kOld); | 13047 data = FindFreeIndex(&index); |
12799 WriteSentinel(data, TestEntryLength()); | 13048 ASSERT(!data.IsNull()); |
12800 intptr_t data_pos = old_num * TestEntryLength(); | 13049 intptr_t data_pos = index * TestEntryLength(); |
12801 Smi& value = Smi::Handle(); | 13050 Smi& value = Smi::Handle(); |
12802 for (intptr_t i = 0; i < class_ids.length(); i++) { | 13051 for (intptr_t i = 0; i < class_ids.length(); i++) { |
12803 // kIllegalCid is used as terminating value, do not add it. | 13052 // kIllegalCid is used as terminating value, do not add it. |
12804 ASSERT(class_ids[i] != kIllegalCid); | 13053 ASSERT(class_ids[i] != kIllegalCid); |
12805 value = Smi::New(class_ids[i]); | 13054 value = Smi::New(class_ids[i]); |
12806 data.SetAt(data_pos++, value); | 13055 data.SetAt(data_pos++, value); |
12807 } | 13056 } |
12808 ASSERT(!target.IsNull()); | 13057 ASSERT(!target.IsNull()); |
12809 data.SetAt(data_pos++, target); | 13058 data.SetAt(data_pos++, target); |
12810 value = Smi::New(1); | 13059 value = Smi::New(1); |
12811 data.SetAt(data_pos, value); | 13060 data.SetAt(data_pos, value); |
12812 // Multithreaded access to ICData requires setting of array to be the last | 13061 // Multithreaded access to ICData requires setting of array to be the last |
12813 // operation. | 13062 // operation. |
12814 set_ic_data_array(data); | 13063 set_ic_data_array(data); |
12815 } | 13064 } |
12816 | 13065 |
12817 | 13066 |
| 13067 RawArray* ICData::FindFreeIndex(intptr_t* index) const { |
| 13068 // The final entry is always the sentinel value, don't consider it |
| 13069 // when searching. |
| 13070 const intptr_t len = Length() - 1; |
| 13071 Array& data = Array::Handle(ic_data()); |
| 13072 *index = len; |
| 13073 for (intptr_t i = 0; i < len; i++) { |
| 13074 if (IsSentinelAt(i)) { |
| 13075 *index = i; |
| 13076 break; |
| 13077 } |
| 13078 } |
| 13079 if (*index < len) { |
| 13080 // We've found a free slot. |
| 13081 return data.raw(); |
| 13082 } |
| 13083 // Append case. |
| 13084 ASSERT(*index == len); |
| 13085 ASSERT(*index >= 0); |
| 13086 // Grow array. |
| 13087 const intptr_t new_len = data.Length() + TestEntryLength(); |
| 13088 data = Array::Grow(data, new_len, Heap::kOld); |
| 13089 WriteSentinel(data, TestEntryLength()); |
| 13090 return data.raw(); |
| 13091 } |
| 13092 |
| 13093 |
| 13094 void ICData::DebugDump() const { |
| 13095 const Function& owner = Function::Handle(Owner()); |
| 13096 THR_Print("ICData::DebugDump\n"); |
| 13097 THR_Print("Owner = %s [deopt=%" Pd "]\n", owner.ToCString(), deopt_id()); |
| 13098 THR_Print("NumArgsTested = %" Pd "\n", NumArgsTested()); |
| 13099 THR_Print("Length = %" Pd "\n", Length()); |
| 13100 THR_Print("NumberOfChecks = %" Pd "\n", NumberOfChecks()); |
| 13101 |
| 13102 GrowableArray<intptr_t> class_ids; |
| 13103 for (intptr_t i = 0; i < NumberOfChecks(); i++) { |
| 13104 THR_Print("Check[%" Pd "]:", i); |
| 13105 GetClassIdsAt(i, &class_ids); |
| 13106 for (intptr_t c = 0; c < class_ids.length(); c++) { |
| 13107 THR_Print(" %" Pd "", class_ids[c]); |
| 13108 } |
| 13109 THR_Print("--- %" Pd " hits\n", GetCountAt(i)); |
| 13110 } |
| 13111 } |
| 13112 |
| 13113 |
| 13114 void ICData::ValidateSentinelLocations() const { |
| 13115 } |
| 13116 |
| 13117 |
12818 void ICData::AddReceiverCheck(intptr_t receiver_class_id, | 13118 void ICData::AddReceiverCheck(intptr_t receiver_class_id, |
12819 const Function& target, | 13119 const Function& target, |
12820 intptr_t count) const { | 13120 intptr_t count) const { |
12821 #if defined(DEBUG) | 13121 #if defined(DEBUG) |
12822 GrowableArray<intptr_t> class_ids(1); | 13122 GrowableArray<intptr_t> class_ids(1); |
12823 class_ids.Add(receiver_class_id); | 13123 class_ids.Add(receiver_class_id); |
12824 ASSERT(!HasCheck(class_ids)); | 13124 ASSERT(!HasCheck(class_ids)); |
12825 #endif // DEBUG | 13125 #endif // DEBUG |
12826 ASSERT(!target.IsNull()); | 13126 ASSERT(!target.IsNull()); |
12827 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. | 13127 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. |
12828 ASSERT(receiver_class_id != kIllegalCid); | 13128 ASSERT(receiver_class_id != kIllegalCid); |
12829 | 13129 |
12830 const intptr_t old_num = NumberOfChecks(); | 13130 intptr_t index = -1; |
12831 Array& data = Array::Handle(ic_data()); | 13131 Array& data = Array::Handle(FindFreeIndex(&index)); |
12832 const intptr_t new_len = data.Length() + TestEntryLength(); | 13132 intptr_t data_pos = index * TestEntryLength(); |
12833 data = Array::Grow(data, new_len, Heap::kOld); | |
12834 WriteSentinel(data, TestEntryLength()); | |
12835 intptr_t data_pos = old_num * TestEntryLength(); | |
12836 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { | 13133 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { |
12837 ASSERT(GetReceiverClassIdAt(0) != kSmiCid); | 13134 ASSERT(GetReceiverClassIdAt(0) != kSmiCid); |
12838 // Move class occupying position 0 to the data_pos. | 13135 // Move class occupying position 0 to the data_pos. |
12839 for (intptr_t i = 0; i < TestEntryLength(); i++) { | 13136 for (intptr_t i = 0; i < TestEntryLength(); i++) { |
12840 data.SetAt(data_pos + i, Object::Handle(data.At(i))); | 13137 data.SetAt(data_pos + i, Object::Handle(data.At(i))); |
12841 } | 13138 } |
12842 // Insert kSmiCid in position 0. | 13139 // Insert kSmiCid in position 0. |
12843 data_pos = 0; | 13140 data_pos = 0; |
12844 } | 13141 } |
12845 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); | 13142 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); |
(...skipping 24 matching lines...) Expand all Loading... |
12870 class_ids->Clear(); | 13167 class_ids->Clear(); |
12871 const Array& data = Array::Handle(ic_data()); | 13168 const Array& data = Array::Handle(ic_data()); |
12872 intptr_t data_pos = index * TestEntryLength(); | 13169 intptr_t data_pos = index * TestEntryLength(); |
12873 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 13170 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
12874 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); | 13171 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); |
12875 } | 13172 } |
12876 (*target) ^= data.At(data_pos++); | 13173 (*target) ^= data.At(data_pos++); |
12877 } | 13174 } |
12878 | 13175 |
12879 | 13176 |
| 13177 bool ICData::IsSentinelAt(intptr_t index) const { |
| 13178 ASSERT(index < Length()); |
| 13179 const Array& data = Array::Handle(ic_data()); |
| 13180 const intptr_t entry_length = TestEntryLength(); |
| 13181 intptr_t data_pos = index * TestEntryLength(); |
| 13182 for (intptr_t i = 0; i < entry_length; i++) { |
| 13183 if (data.At(data_pos++) != smi_illegal_cid().raw()) { |
| 13184 return false; |
| 13185 } |
| 13186 } |
| 13187 // The entry at |index| was filled with the value kIllegalCid. |
| 13188 return true; |
| 13189 } |
| 13190 |
| 13191 |
12880 void ICData::GetClassIdsAt(intptr_t index, | 13192 void ICData::GetClassIdsAt(intptr_t index, |
12881 GrowableArray<intptr_t>* class_ids) const { | 13193 GrowableArray<intptr_t>* class_ids) const { |
12882 ASSERT(index < NumberOfChecks()); | 13194 ASSERT(index < Length()); |
12883 ASSERT(class_ids != NULL); | 13195 ASSERT(class_ids != NULL); |
| 13196 ASSERT(!IsSentinelAt(index)); |
12884 class_ids->Clear(); | 13197 class_ids->Clear(); |
12885 const Array& data = Array::Handle(ic_data()); | 13198 const Array& data = Array::Handle(ic_data()); |
12886 intptr_t data_pos = index * TestEntryLength(); | 13199 intptr_t data_pos = index * TestEntryLength(); |
12887 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 13200 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
12888 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); | 13201 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); |
12889 } | 13202 } |
12890 } | 13203 } |
12891 | 13204 |
12892 | 13205 |
12893 void ICData::GetOneClassCheckAt(intptr_t index, | 13206 void ICData::GetOneClassCheckAt(intptr_t index, |
(...skipping 18 matching lines...) Expand all Loading... |
12912 | 13225 |
12913 | 13226 |
12914 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { | 13227 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { |
12915 GrowableArray<intptr_t> class_ids; | 13228 GrowableArray<intptr_t> class_ids; |
12916 GetClassIdsAt(index, &class_ids); | 13229 GetClassIdsAt(index, &class_ids); |
12917 return class_ids[arg_nr]; | 13230 return class_ids[arg_nr]; |
12918 } | 13231 } |
12919 | 13232 |
12920 | 13233 |
12921 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { | 13234 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { |
12922 ASSERT(index < NumberOfChecks()); | 13235 ASSERT(index < Length()); |
| 13236 ASSERT(!IsSentinelAt(index)); |
12923 const intptr_t data_pos = index * TestEntryLength(); | 13237 const intptr_t data_pos = index * TestEntryLength(); |
12924 NoSafepointScope no_safepoint; | 13238 NoSafepointScope no_safepoint; |
12925 RawArray* raw_data = ic_data(); | 13239 RawArray* raw_data = ic_data(); |
12926 return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos])); | 13240 return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos])); |
12927 } | 13241 } |
12928 | 13242 |
12929 | 13243 |
12930 RawFunction* ICData::GetTargetAt(intptr_t index) const { | 13244 RawFunction* ICData::GetTargetAt(intptr_t index) const { |
12931 ASSERT(Isolate::Current()->compilation_allowed()); | 13245 ASSERT(Isolate::Current()->compilation_allowed()); |
12932 const intptr_t data_pos = index * TestEntryLength() + NumArgsTested(); | 13246 const intptr_t data_pos = index * TestEntryLength() + NumArgsTested(); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13116 &Function::ZoneHandle(GetTargetAt(i)))); | 13430 &Function::ZoneHandle(GetTargetAt(i)))); |
13117 } | 13431 } |
13118 } | 13432 } |
13119 aggregate.Sort(CidCount::HighestCountFirst); | 13433 aggregate.Sort(CidCount::HighestCountFirst); |
13120 | 13434 |
13121 ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested)); | 13435 ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested)); |
13122 ASSERT(result.NumberOfChecks() == 0); | 13436 ASSERT(result.NumberOfChecks() == 0); |
13123 // Room for all entries and the sentinel. | 13437 // Room for all entries and the sentinel. |
13124 const intptr_t data_len = | 13438 const intptr_t data_len = |
13125 result.TestEntryLength() * (aggregate.length() + 1); | 13439 result.TestEntryLength() * (aggregate.length() + 1); |
| 13440 // Allocate the array but do not assign it to result until we have populated |
| 13441 // it with the aggregate data and the terminating sentinel. |
13126 const Array& data = Array::Handle(Array::New(data_len, Heap::kOld)); | 13442 const Array& data = Array::Handle(Array::New(data_len, Heap::kOld)); |
13127 result.set_ic_data_array(data); | |
13128 ASSERT(result.NumberOfChecks() == aggregate.length()); | |
13129 | |
13130 intptr_t pos = 0; | 13443 intptr_t pos = 0; |
13131 for (intptr_t i = 0; i < aggregate.length(); i++) { | 13444 for (intptr_t i = 0; i < aggregate.length(); i++) { |
13132 data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid))); | 13445 data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid))); |
13133 data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function); | 13446 data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function); |
13134 data.SetAt(pos + CountIndexFor(1), | 13447 data.SetAt(pos + CountIndexFor(1), |
13135 Smi::Handle(Smi::New(aggregate[i].count))); | 13448 Smi::Handle(Smi::New(aggregate[i].count))); |
13136 | 13449 |
13137 pos += result.TestEntryLength(); | 13450 pos += result.TestEntryLength(); |
13138 } | 13451 } |
13139 WriteSentinel(data, result.TestEntryLength()); | 13452 WriteSentinel(data, result.TestEntryLength()); |
13140 result.set_ic_data_array(data); | 13453 result.set_ic_data_array(data); |
| 13454 ASSERT(result.NumberOfChecks() == aggregate.length()); |
13141 return result.raw(); | 13455 return result.raw(); |
13142 } | 13456 } |
13143 | 13457 |
13144 | 13458 |
13145 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { | 13459 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { |
13146 if (NumberOfChecks() == 0) return false; | 13460 if (NumberOfChecks() == 0) return false; |
13147 Class& cls = Class::Handle(); | 13461 Class& cls = Class::Handle(); |
13148 const intptr_t len = NumberOfChecks(); | 13462 const intptr_t len = NumberOfChecks(); |
13149 for (intptr_t i = 0; i < len; i++) { | 13463 for (intptr_t i = 0; i < len; i++) { |
13150 if (IsUsedAt(i)) { | 13464 if (IsUsedAt(i)) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13277 result.set_deopt_id(deopt_id); | 13591 result.set_deopt_id(deopt_id); |
13278 result.set_state_bits(0); | 13592 result.set_state_bits(0); |
13279 #if defined(TAG_IC_DATA) | 13593 #if defined(TAG_IC_DATA) |
13280 result.set_tag(-1); | 13594 result.set_tag(-1); |
13281 #endif | 13595 #endif |
13282 result.SetNumArgsTested(num_args_tested); | 13596 result.SetNumArgsTested(num_args_tested); |
13283 return result.raw(); | 13597 return result.raw(); |
13284 } | 13598 } |
13285 | 13599 |
13286 | 13600 |
| 13601 bool ICData::IsImmutable() const { |
| 13602 const Array& data = Array::Handle(ic_data()); |
| 13603 return data.IsImmutable(); |
| 13604 } |
| 13605 |
| 13606 |
| 13607 void ICData::ResetData() const { |
| 13608 // Number of array elements in one test entry. |
| 13609 intptr_t len = TestEntryLength(); |
| 13610 // IC data array must be null terminated (sentinel entry). |
| 13611 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); |
| 13612 set_ic_data_array(ic_data); |
| 13613 WriteSentinel(ic_data, len); |
| 13614 } |
| 13615 |
| 13616 |
13287 RawICData* ICData::New() { | 13617 RawICData* ICData::New() { |
13288 ICData& result = ICData::Handle(); | 13618 ICData& result = ICData::Handle(); |
13289 { | 13619 { |
13290 // IC data objects are long living objects, allocate them in old generation. | 13620 // IC data objects are long living objects, allocate them in old generation. |
13291 RawObject* raw = Object::Allocate(ICData::kClassId, | 13621 RawObject* raw = Object::Allocate(ICData::kClassId, |
13292 ICData::InstanceSize(), | 13622 ICData::InstanceSize(), |
13293 Heap::kOld); | 13623 Heap::kOld); |
13294 NoSafepointScope no_safepoint; | 13624 NoSafepointScope no_safepoint; |
13295 result ^= raw; | 13625 result ^= raw; |
13296 } | 13626 } |
(...skipping 2302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15599 } | 15929 } |
15600 | 15930 |
15601 | 15931 |
15602 bool AbstractType::HasResolvedTypeClass() const { | 15932 bool AbstractType::HasResolvedTypeClass() const { |
15603 // AbstractType is an abstract class. | 15933 // AbstractType is an abstract class. |
15604 UNREACHABLE(); | 15934 UNREACHABLE(); |
15605 return false; | 15935 return false; |
15606 } | 15936 } |
15607 | 15937 |
15608 | 15938 |
| 15939 classid_t AbstractType::type_class_id() const { |
| 15940 // AbstractType is an abstract class. |
| 15941 UNREACHABLE(); |
| 15942 return kIllegalCid; |
| 15943 } |
| 15944 |
| 15945 |
15609 RawClass* AbstractType::type_class() const { | 15946 RawClass* AbstractType::type_class() const { |
15610 // AbstractType is an abstract class. | 15947 // AbstractType is an abstract class. |
15611 UNREACHABLE(); | 15948 UNREACHABLE(); |
15612 return Class::null(); | 15949 return Class::null(); |
15613 } | 15950 } |
15614 | 15951 |
15615 | 15952 |
15616 RawUnresolvedClass* AbstractType::unresolved_class() const { | 15953 RawUnresolvedClass* AbstractType::unresolved_class() const { |
15617 // AbstractType is an abstract class. | 15954 // AbstractType is an abstract class. |
15618 UNREACHABLE(); | 15955 UNREACHABLE(); |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16464 } | 16801 } |
16465 | 16802 |
16466 | 16803 |
16467 void Type::SetIsResolved() const { | 16804 void Type::SetIsResolved() const { |
16468 ASSERT(!IsResolved()); | 16805 ASSERT(!IsResolved()); |
16469 set_type_state(RawType::kResolved); | 16806 set_type_state(RawType::kResolved); |
16470 } | 16807 } |
16471 | 16808 |
16472 | 16809 |
16473 bool Type::HasResolvedTypeClass() const { | 16810 bool Type::HasResolvedTypeClass() const { |
16474 return (raw_ptr()->type_class_->GetClassId() == kClassCid); | 16811 return !raw_ptr()->type_class_id_->IsHeapObject(); |
| 16812 } |
| 16813 |
| 16814 |
| 16815 classid_t Type::type_class_id() const { |
| 16816 ASSERT(HasResolvedTypeClass()); |
| 16817 return Smi::Value(reinterpret_cast<RawSmi*>(raw_ptr()->type_class_id_)); |
16475 } | 16818 } |
16476 | 16819 |
16477 | 16820 |
16478 RawClass* Type::type_class() const { | 16821 RawClass* Type::type_class() const { |
16479 #ifdef DEBUG | 16822 return Isolate::Current()->class_table()->At(type_class_id()); |
16480 ASSERT(HasResolvedTypeClass()); | |
16481 Class& type_class = Class::Handle(); | |
16482 type_class ^= raw_ptr()->type_class_; | |
16483 return type_class.raw(); | |
16484 #else | |
16485 return reinterpret_cast<RawClass*>(raw_ptr()->type_class_); | |
16486 #endif | |
16487 } | 16823 } |
16488 | 16824 |
16489 | 16825 |
16490 RawUnresolvedClass* Type::unresolved_class() const { | 16826 RawUnresolvedClass* Type::unresolved_class() const { |
16491 #ifdef DEBUG | 16827 #ifdef DEBUG |
16492 ASSERT(!HasResolvedTypeClass()); | 16828 ASSERT(!HasResolvedTypeClass()); |
16493 UnresolvedClass& unresolved_class = UnresolvedClass::Handle(); | 16829 UnresolvedClass& unresolved_class = UnresolvedClass::Handle(); |
16494 unresolved_class ^= raw_ptr()->type_class_; | 16830 unresolved_class ^= raw_ptr()->type_class_id_; |
16495 ASSERT(!unresolved_class.IsNull()); | 16831 ASSERT(!unresolved_class.IsNull()); |
16496 return unresolved_class.raw(); | 16832 return unresolved_class.raw(); |
16497 #else | 16833 #else |
16498 ASSERT(!Object::Handle(raw_ptr()->type_class_).IsNull()); | 16834 ASSERT(!Object::Handle(raw_ptr()->type_class_id_).IsNull()); |
16499 ASSERT(Object::Handle(raw_ptr()->type_class_).IsUnresolvedClass()); | 16835 ASSERT(Object::Handle(raw_ptr()->type_class_id_).IsUnresolvedClass()); |
16500 return reinterpret_cast<RawUnresolvedClass*>(raw_ptr()->type_class_); | 16836 return reinterpret_cast<RawUnresolvedClass*>(raw_ptr()->type_class_id_); |
16501 #endif | 16837 #endif |
16502 } | 16838 } |
16503 | 16839 |
16504 | 16840 |
16505 bool Type::IsInstantiated(TrailPtr trail) const { | 16841 bool Type::IsInstantiated(TrailPtr trail) const { |
16506 if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) { | 16842 if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) { |
16507 return true; | 16843 return true; |
16508 } | 16844 } |
16509 if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) { | 16845 if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) { |
16510 return false; | 16846 return false; |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17056 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { | 17392 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { |
17057 param_name = sig_fun.ParameterNameAt(i); | 17393 param_name = sig_fun.ParameterNameAt(i); |
17058 result = CombineHashes(result, param_name.Hash()); | 17394 result = CombineHashes(result, param_name.Hash()); |
17059 } | 17395 } |
17060 } | 17396 } |
17061 } | 17397 } |
17062 return FinalizeHash(result); | 17398 return FinalizeHash(result); |
17063 } | 17399 } |
17064 | 17400 |
17065 | 17401 |
17066 void Type::set_type_class(const Object& value) const { | 17402 void Type::set_type_class(const Class& value) const { |
17067 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass())); | 17403 ASSERT(!value.IsNull()); |
17068 StorePointer(&raw_ptr()->type_class_, value.raw()); | 17404 StorePointer(&raw_ptr()->type_class_id_, |
| 17405 reinterpret_cast<RawObject*>(Smi::New(value.id()))); |
17069 } | 17406 } |
17070 | 17407 |
17071 | 17408 |
| 17409 void Type::set_unresolved_class(const Object& value) const { |
| 17410 ASSERT(!value.IsNull() && value.IsUnresolvedClass()); |
| 17411 StorePointer(&raw_ptr()->type_class_id_, value.raw()); |
| 17412 } |
| 17413 |
| 17414 |
17072 void Type::set_arguments(const TypeArguments& value) const { | 17415 void Type::set_arguments(const TypeArguments& value) const { |
17073 ASSERT(!IsCanonical()); | 17416 ASSERT(!IsCanonical()); |
17074 StorePointer(&raw_ptr()->arguments_, value.raw()); | 17417 StorePointer(&raw_ptr()->arguments_, value.raw()); |
17075 } | 17418 } |
17076 | 17419 |
17077 | 17420 |
17078 RawType* Type::New(Heap::Space space) { | 17421 RawType* Type::New(Heap::Space space) { |
17079 RawObject* raw = Object::Allocate(Type::kClassId, | 17422 RawObject* raw = Object::Allocate(Type::kClassId, |
17080 Type::InstanceSize(), | 17423 Type::InstanceSize(), |
17081 space); | 17424 space); |
17082 return reinterpret_cast<RawType*>(raw); | 17425 return reinterpret_cast<RawType*>(raw); |
17083 } | 17426 } |
17084 | 17427 |
17085 | 17428 |
17086 RawType* Type::New(const Object& clazz, | 17429 RawType* Type::New(const Object& clazz, |
17087 const TypeArguments& arguments, | 17430 const TypeArguments& arguments, |
17088 TokenPosition token_pos, | 17431 TokenPosition token_pos, |
17089 Heap::Space space) { | 17432 Heap::Space space) { |
17090 const Type& result = Type::Handle(Type::New(space)); | 17433 const Type& result = Type::Handle(Type::New(space)); |
17091 result.set_type_class(clazz); | 17434 if (clazz.IsClass()) { |
| 17435 result.set_type_class(Class::Cast(clazz)); |
| 17436 } else { |
| 17437 result.set_unresolved_class(clazz); |
| 17438 } |
17092 result.set_arguments(arguments); | 17439 result.set_arguments(arguments); |
17093 result.set_token_pos(token_pos); | 17440 result.set_token_pos(token_pos); |
17094 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); | 17441 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); |
17095 return result.raw(); | 17442 return result.raw(); |
17096 } | 17443 } |
17097 | 17444 |
17098 | 17445 |
17099 void Type::set_token_pos(TokenPosition token_pos) const { | 17446 void Type::set_token_pos(TokenPosition token_pos) const { |
17100 ASSERT(!token_pos.IsClassifying()); | 17447 ASSERT(!token_pos.IsClassifying()); |
17101 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 17448 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17329 } | 17676 } |
17330 if (IsFinalized() == other_type_param.IsFinalized()) { | 17677 if (IsFinalized() == other_type_param.IsFinalized()) { |
17331 return index() == other_type_param.index(); | 17678 return index() == other_type_param.index(); |
17332 } | 17679 } |
17333 return name() == other_type_param.name(); | 17680 return name() == other_type_param.name(); |
17334 } | 17681 } |
17335 | 17682 |
17336 | 17683 |
17337 void TypeParameter::set_parameterized_class(const Class& value) const { | 17684 void TypeParameter::set_parameterized_class(const Class& value) const { |
17338 // Set value may be null. | 17685 // Set value may be null. |
17339 StorePointer(&raw_ptr()->parameterized_class_, value.raw()); | 17686 classid_t cid = kIllegalCid; |
| 17687 if (!value.IsNull()) { |
| 17688 cid = value.id(); |
| 17689 } |
| 17690 StorePointer(&raw_ptr()->parameterized_class_id_, |
| 17691 reinterpret_cast<RawObject*>(Smi::New(cid))); |
17340 } | 17692 } |
17341 | 17693 |
17342 | 17694 |
| 17695 classid_t TypeParameter::parameterized_class_id() const { |
| 17696 return Smi::Value(Smi::RawCast(raw_ptr()->parameterized_class_id_)); |
| 17697 } |
| 17698 |
| 17699 |
| 17700 RawClass* TypeParameter::parameterized_class() const { |
| 17701 classid_t cid = parameterized_class_id(); |
| 17702 if (cid == kIllegalCid) { |
| 17703 return Class::null(); |
| 17704 } |
| 17705 return Isolate::Current()->class_table()->At(cid); |
| 17706 } |
| 17707 |
| 17708 |
17343 void TypeParameter::set_index(intptr_t value) const { | 17709 void TypeParameter::set_index(intptr_t value) const { |
17344 ASSERT(value >= 0); | 17710 ASSERT(value >= 0); |
17345 ASSERT(Utils::IsInt(16, value)); | 17711 ASSERT(Utils::IsInt(16, value)); |
17346 StoreNonPointer(&raw_ptr()->index_, value); | 17712 StoreNonPointer(&raw_ptr()->index_, value); |
17347 } | 17713 } |
17348 | 17714 |
17349 | 17715 |
17350 void TypeParameter::set_name(const String& value) const { | 17716 void TypeParameter::set_name(const String& value) const { |
17351 ASSERT(value.IsSymbol()); | 17717 ASSERT(value.IsSymbol()); |
17352 StorePointer(&raw_ptr()->name_, value.raw()); | 17718 StorePointer(&raw_ptr()->name_, value.raw()); |
(...skipping 5099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
22452 return UserTag::null(); | 22818 return UserTag::null(); |
22453 } | 22819 } |
22454 | 22820 |
22455 | 22821 |
22456 const char* UserTag::ToCString() const { | 22822 const char* UserTag::ToCString() const { |
22457 const String& tag_label = String::Handle(label()); | 22823 const String& tag_label = String::Handle(label()); |
22458 return tag_label.ToCString(); | 22824 return tag_label.ToCString(); |
22459 } | 22825 } |
22460 | 22826 |
22461 } // namespace dart | 22827 } // namespace dart |
OLD | NEW |