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 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8920 void Script::set_source(const String& value) const { | 9013 void Script::set_source(const String& value) const { |
8921 StorePointer(&raw_ptr()->source_, value.raw()); | 9014 StorePointer(&raw_ptr()->source_, value.raw()); |
8922 } | 9015 } |
8923 | 9016 |
8924 | 9017 |
8925 void Script::set_kind(RawScript::Kind value) const { | 9018 void Script::set_kind(RawScript::Kind value) const { |
8926 StoreNonPointer(&raw_ptr()->kind_, value); | 9019 StoreNonPointer(&raw_ptr()->kind_, value); |
8927 } | 9020 } |
8928 | 9021 |
8929 | 9022 |
9023 void Script::set_load_timestamp(int64_t value) const { | |
9024 StoreNonPointer(&raw_ptr()->load_timestamp_, value); | |
9025 } | |
9026 | |
9027 | |
8930 void Script::set_tokens(const TokenStream& value) const { | 9028 void Script::set_tokens(const TokenStream& value) const { |
8931 StorePointer(&raw_ptr()->tokens_, value.raw()); | 9029 StorePointer(&raw_ptr()->tokens_, value.raw()); |
8932 } | 9030 } |
8933 | 9031 |
8934 | 9032 |
8935 void Script::Tokenize(const String& private_key, | 9033 void Script::Tokenize(const String& private_key, |
8936 bool use_shared_tokens) const { | 9034 bool use_shared_tokens) const { |
8937 Thread* thread = Thread::Current(); | 9035 Thread* thread = Thread::Current(); |
8938 Zone* zone = thread->zone(); | 9036 Zone* zone = thread->zone(); |
8939 const TokenStream& tkns = TokenStream::Handle(zone, tokens()); | 9037 const TokenStream& tkns = TokenStream::Handle(zone, tokens()); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9173 | 9271 |
9174 RawScript* Script::New(const String& url, | 9272 RawScript* Script::New(const String& url, |
9175 const String& source, | 9273 const String& source, |
9176 RawScript::Kind kind) { | 9274 RawScript::Kind kind) { |
9177 Thread* thread = Thread::Current(); | 9275 Thread* thread = Thread::Current(); |
9178 Zone* zone = thread->zone(); | 9276 Zone* zone = thread->zone(); |
9179 const Script& result = Script::Handle(zone, Script::New()); | 9277 const Script& result = Script::Handle(zone, Script::New()); |
9180 result.set_url(String::Handle(zone, Symbols::New(thread, url))); | 9278 result.set_url(String::Handle(zone, Symbols::New(thread, url))); |
9181 result.set_source(source); | 9279 result.set_source(source); |
9182 result.set_kind(kind); | 9280 result.set_kind(kind); |
9281 result.set_load_timestamp(FLAG_remove_script_timestamps_for_test | |
9282 ? 0 : OS::GetCurrentTimeMillis()); | |
rmacnak
2016/05/13 17:59:34
monotonic time?
Cutch
2016/05/17 18:03:52
Sticking with non-monotonic. We report this time t
| |
9183 result.SetLocationOffset(0, 0); | 9283 result.SetLocationOffset(0, 0); |
9184 return result.raw(); | 9284 return result.raw(); |
9185 } | 9285 } |
9186 | 9286 |
9187 | 9287 |
9188 const char* Script::ToCString() const { | 9288 const char* Script::ToCString() const { |
9189 return "Script"; | 9289 const String& name = String::Handle(url()); |
9290 return OS::SCreate(Thread::Current()->zone(), "Script(%s)", name.ToCString()); | |
9190 } | 9291 } |
9191 | 9292 |
9192 | 9293 |
9193 RawLibrary* Script::FindLibrary() const { | 9294 RawLibrary* Script::FindLibrary() const { |
9194 Thread* thread = Thread::Current(); | 9295 Thread* thread = Thread::Current(); |
9195 Zone* zone = thread->zone(); | 9296 Zone* zone = thread->zone(); |
9196 Isolate* isolate = thread->isolate(); | 9297 Isolate* isolate = thread->isolate(); |
9197 const GrowableObjectArray& libs = GrowableObjectArray::Handle(zone, | 9298 const GrowableObjectArray& libs = GrowableObjectArray::Handle(zone, |
9198 isolate->object_store()->libraries()); | 9299 isolate->object_store()->libraries()); |
9199 Library& lib = Library::Handle(zone); | 9300 Library& lib = Library::Handle(zone); |
(...skipping 3469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12669 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { | 12770 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { |
12670 return num_args + 1 /* target function*/ + 1 /* frequency */; | 12771 return num_args + 1 /* target function*/ + 1 /* frequency */; |
12671 } | 12772 } |
12672 | 12773 |
12673 | 12774 |
12674 intptr_t ICData::TestEntryLength() const { | 12775 intptr_t ICData::TestEntryLength() const { |
12675 return TestEntryLengthFor(NumArgsTested()); | 12776 return TestEntryLengthFor(NumArgsTested()); |
12676 } | 12777 } |
12677 | 12778 |
12678 | 12779 |
12780 intptr_t ICData::Length() const { | |
12781 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()); | |
12782 } | |
12783 | |
12784 | |
12679 intptr_t ICData::NumberOfChecks() const { | 12785 intptr_t ICData::NumberOfChecks() const { |
12680 // Do not count the sentinel; | 12786 const intptr_t length = Length(); |
12681 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; | 12787 for (intptr_t i = 0; i < length; i++) { |
12788 if (IsSentinelAt(i)) { | |
12789 return i; | |
12790 } | |
12791 } | |
12792 UNREACHABLE(); | |
12793 return -1; | |
12682 } | 12794 } |
12683 | 12795 |
12684 | 12796 |
12685 // Discounts any checks with usage of zero. | 12797 // Discounts any checks with usage of zero. |
12686 intptr_t ICData::NumberOfUsedChecks() const { | 12798 intptr_t ICData::NumberOfUsedChecks() const { |
12687 intptr_t n = NumberOfChecks(); | 12799 intptr_t n = NumberOfChecks(); |
12688 if (n == 0) { | 12800 if (n == 0) { |
12689 return 0; | 12801 return 0; |
12690 } | 12802 } |
12691 intptr_t count = 0; | 12803 intptr_t count = 0; |
(...skipping 16 matching lines...) Expand all Loading... | |
12708 | 12820 |
12709 #if defined(DEBUG) | 12821 #if defined(DEBUG) |
12710 // Used in asserts to verify that a check is not added twice. | 12822 // Used in asserts to verify that a check is not added twice. |
12711 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { | 12823 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { |
12712 const intptr_t len = NumberOfChecks(); | 12824 const intptr_t len = NumberOfChecks(); |
12713 for (intptr_t i = 0; i < len; i++) { | 12825 for (intptr_t i = 0; i < len; i++) { |
12714 GrowableArray<intptr_t> class_ids; | 12826 GrowableArray<intptr_t> class_ids; |
12715 GetClassIdsAt(i, &class_ids); | 12827 GetClassIdsAt(i, &class_ids); |
12716 bool matches = true; | 12828 bool matches = true; |
12717 for (intptr_t k = 0; k < class_ids.length(); k++) { | 12829 for (intptr_t k = 0; k < class_ids.length(); k++) { |
12830 ASSERT(class_ids[k] != kIllegalCid); | |
12718 if (class_ids[k] != cids[k]) { | 12831 if (class_ids[k] != cids[k]) { |
12719 matches = false; | 12832 matches = false; |
12720 break; | 12833 break; |
12721 } | 12834 } |
12722 } | 12835 } |
12723 if (matches) { | 12836 if (matches) { |
12724 return true; | 12837 return true; |
12725 } | 12838 } |
12726 } | 12839 } |
12727 return false; | 12840 return false; |
12728 } | 12841 } |
12729 #endif // DEBUG | 12842 #endif // DEBUG |
12730 | 12843 |
12731 | 12844 |
12845 void ICData::WriteSentinelAt(intptr_t index) const { | |
12846 const intptr_t len = Length(); | |
12847 ASSERT(index >= 0); | |
12848 ASSERT(index < len); | |
12849 Array& data = Array::Handle(ic_data()); | |
12850 const intptr_t start = index * TestEntryLength(); | |
12851 const intptr_t end = start + TestEntryLength(); | |
12852 for (intptr_t i = start; i < end; i++) { | |
12853 data.SetAt(i, smi_illegal_cid()); | |
12854 } | |
12855 } | |
12856 | |
12857 | |
12858 void ICData::ClearCountAt(intptr_t index) const { | |
12859 const intptr_t len = NumberOfChecks(); | |
12860 ASSERT(index >= 0); | |
12861 ASSERT(index < len); | |
12862 SetCountAt(index, 0); | |
12863 } | |
12864 | |
12865 | |
12866 void ICData::ClearWithSentinel() const { | |
12867 if (IsImmutable()) { | |
12868 return; | |
12869 } | |
12870 // Write the sentinel value into all entries except the first one. | |
12871 const intptr_t len = Length(); | |
12872 if (len == 0) { | |
12873 return; | |
12874 } | |
12875 // The final entry is always the sentinel. | |
12876 ASSERT(IsSentinelAt(len - 1)); | |
12877 for (intptr_t i = len - 1; i > 0; i--) { | |
12878 WriteSentinelAt(i); | |
12879 } | |
12880 if (NumArgsTested() != 2) { | |
12881 // Not the smi fast path case, write sentinel to first one and exit. | |
12882 WriteSentinelAt(0); | |
12883 return; | |
12884 } | |
12885 if (IsSentinelAt(0)) { | |
12886 return; | |
12887 } | |
12888 Zone* zone = Thread::Current()->zone(); | |
12889 const String& name = String::Handle(target_name()); | |
12890 const Class& smi_class = Class::Handle(Smi::Class()); | |
12891 const Function& smi_op_target = | |
12892 Function::Handle(Resolver::ResolveDynamicAnyArgs(zone, smi_class, name)); | |
12893 GrowableArray<intptr_t> class_ids(2); | |
12894 Function& target = Function::Handle(); | |
12895 GetCheckAt(0, &class_ids, &target); | |
12896 if ((target.raw() == smi_op_target.raw()) && | |
12897 (class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | |
12898 // The smi fast path case, preserve the initial entry but reset the count. | |
12899 ClearCountAt(0); | |
12900 return; | |
12901 } | |
12902 WriteSentinelAt(0); | |
12903 } | |
12904 | |
12905 | |
12906 void ICData::ClearAndSetStaticTarget(const Function& func) const { | |
12907 if (IsImmutable()) { | |
12908 return; | |
12909 } | |
12910 const intptr_t len = Length(); | |
12911 if (len == 0) { | |
12912 return; | |
12913 } | |
12914 // The final entry is always the sentinel. | |
12915 ASSERT(IsSentinelAt(len - 1)); | |
12916 if (NumArgsTested() == 0) { | |
12917 // No type feedback is being collected. | |
12918 const Array& data = Array::Handle(ic_data()); | |
12919 // Static calls with no argument checks hold only one target and the | |
12920 // sentinel value. | |
12921 ASSERT(len == 2); | |
12922 // Static calls with no argument checks only need two words. | |
12923 ASSERT(TestEntryLength() == 2); | |
12924 // Set the target. | |
12925 data.SetAt(0, func); | |
12926 // Set count to 0 as this is called during compilation, before the | |
12927 // call has been executed. | |
12928 const Smi& value = Smi::Handle(Smi::New(0)); | |
12929 data.SetAt(1, value); | |
12930 } else { | |
12931 // Type feedback on arguments is being collected. | |
12932 const Array& data = Array::Handle(ic_data()); | |
12933 | |
12934 // Fill all but the first entry with the sentinel. | |
12935 for (intptr_t i = len - 1; i > 0; i--) { | |
12936 WriteSentinelAt(i); | |
12937 } | |
12938 // Rewrite the dummy entry. | |
12939 const Smi& object_cid = Smi::Handle(Smi::New(kObjectCid)); | |
12940 for (intptr_t i = 0; i < NumArgsTested(); i++) { | |
12941 data.SetAt(i, object_cid); | |
12942 } | |
12943 data.SetAt(NumArgsTested(), func); | |
12944 const Smi& value = Smi::Handle(Smi::New(0)); | |
12945 data.SetAt(NumArgsTested() + 1, value); | |
12946 } | |
12947 } | |
12948 | |
12949 | |
12950 // Add an initial Smi/Smi check with count 0. | |
12951 bool ICData::AddSmiSmiCheckForFastSmiStubs() const { | |
12952 bool is_smi_two_args_op = false; | |
12953 | |
12954 ASSERT(NumArgsTested() == 2); | |
12955 const String& name = String::Handle(target_name()); | |
12956 const Class& smi_class = Class::Handle(Smi::Class()); | |
12957 Zone* zone = Thread::Current()->zone(); | |
12958 const Function& smi_op_target = | |
12959 Function::Handle(Resolver::ResolveDynamicAnyArgs(zone, smi_class, name)); | |
12960 if (NumberOfChecks() == 0) { | |
12961 GrowableArray<intptr_t> class_ids(2); | |
12962 class_ids.Add(kSmiCid); | |
12963 class_ids.Add(kSmiCid); | |
12964 AddCheck(class_ids, smi_op_target); | |
12965 // 'AddCheck' sets the initial count to 1. | |
12966 SetCountAt(0, 0); | |
12967 is_smi_two_args_op = true; | |
12968 } else if (NumberOfChecks() == 1) { | |
12969 GrowableArray<intptr_t> class_ids(2); | |
12970 Function& target = Function::Handle(); | |
12971 GetCheckAt(0, &class_ids, &target); | |
12972 if ((target.raw() == smi_op_target.raw()) && | |
12973 (class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | |
12974 is_smi_two_args_op = true; | |
12975 } | |
12976 } | |
12977 return is_smi_two_args_op; | |
12978 } | |
12979 | |
12980 | |
12732 // Used for unoptimized static calls when no class-ids are checked. | 12981 // Used for unoptimized static calls when no class-ids are checked. |
12733 void ICData::AddTarget(const Function& target) const { | 12982 void ICData::AddTarget(const Function& target) const { |
12734 ASSERT(!target.IsNull()); | 12983 ASSERT(!target.IsNull()); |
12735 if (NumArgsTested() > 0) { | 12984 if (NumArgsTested() > 0) { |
12736 // Create a fake cid entry, so that we can store the target. | 12985 // Create a fake cid entry, so that we can store the target. |
12737 if (NumArgsTested() == 1) { | 12986 if (NumArgsTested() == 1) { |
12738 AddReceiverCheck(kObjectCid, target, 1); | 12987 AddReceiverCheck(kObjectCid, target, 1); |
12739 } else { | 12988 } else { |
12740 GrowableArray<intptr_t> class_ids(NumArgsTested()); | 12989 GrowableArray<intptr_t> class_ids(NumArgsTested()); |
12741 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 12990 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12791 // Replace dummy entry. | 13040 // Replace dummy entry. |
12792 Smi& value = Smi::Handle(); | 13041 Smi& value = Smi::Handle(); |
12793 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 13042 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
12794 ASSERT(class_ids[i] != kIllegalCid); | 13043 ASSERT(class_ids[i] != kIllegalCid); |
12795 value = Smi::New(class_ids[i]); | 13044 value = Smi::New(class_ids[i]); |
12796 data.SetAt(i, value); | 13045 data.SetAt(i, value); |
12797 } | 13046 } |
12798 return; | 13047 return; |
12799 } | 13048 } |
12800 } | 13049 } |
12801 const intptr_t new_len = data.Length() + TestEntryLength(); | 13050 intptr_t index = -1; |
12802 data = Array::Grow(data, new_len, Heap::kOld); | 13051 data = FindFreeIndex(&index); |
12803 WriteSentinel(data, TestEntryLength()); | 13052 ASSERT(!data.IsNull()); |
12804 intptr_t data_pos = old_num * TestEntryLength(); | 13053 intptr_t data_pos = index * TestEntryLength(); |
12805 Smi& value = Smi::Handle(); | 13054 Smi& value = Smi::Handle(); |
12806 for (intptr_t i = 0; i < class_ids.length(); i++) { | 13055 for (intptr_t i = 0; i < class_ids.length(); i++) { |
12807 // kIllegalCid is used as terminating value, do not add it. | 13056 // kIllegalCid is used as terminating value, do not add it. |
12808 ASSERT(class_ids[i] != kIllegalCid); | 13057 ASSERT(class_ids[i] != kIllegalCid); |
12809 value = Smi::New(class_ids[i]); | 13058 value = Smi::New(class_ids[i]); |
12810 data.SetAt(data_pos++, value); | 13059 data.SetAt(data_pos++, value); |
12811 } | 13060 } |
12812 ASSERT(!target.IsNull()); | 13061 ASSERT(!target.IsNull()); |
12813 data.SetAt(data_pos++, target); | 13062 data.SetAt(data_pos++, target); |
12814 value = Smi::New(1); | 13063 value = Smi::New(1); |
12815 data.SetAt(data_pos, value); | 13064 data.SetAt(data_pos, value); |
12816 // Multithreaded access to ICData requires setting of array to be the last | 13065 // Multithreaded access to ICData requires setting of array to be the last |
12817 // operation. | 13066 // operation. |
12818 set_ic_data_array(data); | 13067 set_ic_data_array(data); |
12819 } | 13068 } |
12820 | 13069 |
12821 | 13070 |
13071 RawArray* ICData::FindFreeIndex(intptr_t* index) const { | |
13072 // The final entry is always the sentinel value, don't consider it | |
13073 // when searching. | |
13074 const intptr_t len = Length() - 1; | |
13075 Array& data = Array::Handle(ic_data()); | |
13076 *index = len; | |
13077 for (intptr_t i = 0; i < len; i++) { | |
13078 if (IsSentinelAt(i)) { | |
13079 *index = i; | |
13080 break; | |
13081 } | |
13082 } | |
13083 if (*index < len) { | |
13084 // We've found a free slot. | |
13085 return data.raw(); | |
13086 } | |
13087 // Append case. | |
13088 ASSERT(*index == len); | |
13089 ASSERT(*index >= 0); | |
13090 // Grow array. | |
13091 const intptr_t new_len = data.Length() + TestEntryLength(); | |
13092 data = Array::Grow(data, new_len, Heap::kOld); | |
13093 WriteSentinel(data, TestEntryLength()); | |
13094 return data.raw(); | |
13095 } | |
13096 | |
13097 | |
13098 void ICData::DebugDump() const { | |
13099 const Function& owner = Function::Handle(Owner()); | |
13100 THR_Print("ICData::DebugDump\n"); | |
13101 THR_Print("Owner = %s [deopt=%" Pd "]\n", owner.ToCString(), deopt_id()); | |
13102 THR_Print("NumArgsTested = %" Pd "\n", NumArgsTested()); | |
13103 THR_Print("Length = %" Pd "\n", Length()); | |
13104 THR_Print("NumberOfChecks = %" Pd "\n", NumberOfChecks()); | |
13105 | |
13106 GrowableArray<intptr_t> class_ids; | |
13107 for (intptr_t i = 0; i < NumberOfChecks(); i++) { | |
13108 THR_Print("Check[%" Pd "]:", i); | |
13109 GetClassIdsAt(i, &class_ids); | |
13110 for (intptr_t c = 0; c < class_ids.length(); c++) { | |
13111 THR_Print(" %" Pd "", class_ids[c]); | |
13112 } | |
13113 THR_Print("--- %" Pd " hits\n", GetCountAt(i)); | |
13114 } | |
13115 } | |
13116 | |
13117 | |
13118 void ICData::ValidateSentinelLocations() const { | |
13119 } | |
13120 | |
13121 | |
12822 void ICData::AddReceiverCheck(intptr_t receiver_class_id, | 13122 void ICData::AddReceiverCheck(intptr_t receiver_class_id, |
12823 const Function& target, | 13123 const Function& target, |
12824 intptr_t count) const { | 13124 intptr_t count) const { |
12825 #if defined(DEBUG) | 13125 #if defined(DEBUG) |
12826 GrowableArray<intptr_t> class_ids(1); | 13126 GrowableArray<intptr_t> class_ids(1); |
12827 class_ids.Add(receiver_class_id); | 13127 class_ids.Add(receiver_class_id); |
12828 ASSERT(!HasCheck(class_ids)); | 13128 ASSERT(!HasCheck(class_ids)); |
12829 #endif // DEBUG | 13129 #endif // DEBUG |
12830 ASSERT(!target.IsNull()); | 13130 ASSERT(!target.IsNull()); |
12831 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. | 13131 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. |
12832 ASSERT(receiver_class_id != kIllegalCid); | 13132 ASSERT(receiver_class_id != kIllegalCid); |
12833 | 13133 |
12834 const intptr_t old_num = NumberOfChecks(); | 13134 intptr_t index = -1; |
12835 Array& data = Array::Handle(ic_data()); | 13135 Array& data = Array::Handle(FindFreeIndex(&index)); |
12836 const intptr_t new_len = data.Length() + TestEntryLength(); | 13136 intptr_t data_pos = index * TestEntryLength(); |
12837 data = Array::Grow(data, new_len, Heap::kOld); | |
12838 WriteSentinel(data, TestEntryLength()); | |
12839 intptr_t data_pos = old_num * TestEntryLength(); | |
12840 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { | 13137 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { |
12841 ASSERT(GetReceiverClassIdAt(0) != kSmiCid); | 13138 ASSERT(GetReceiverClassIdAt(0) != kSmiCid); |
12842 // Move class occupying position 0 to the data_pos. | 13139 // Move class occupying position 0 to the data_pos. |
12843 for (intptr_t i = 0; i < TestEntryLength(); i++) { | 13140 for (intptr_t i = 0; i < TestEntryLength(); i++) { |
12844 data.SetAt(data_pos + i, Object::Handle(data.At(i))); | 13141 data.SetAt(data_pos + i, Object::Handle(data.At(i))); |
12845 } | 13142 } |
12846 // Insert kSmiCid in position 0. | 13143 // Insert kSmiCid in position 0. |
12847 data_pos = 0; | 13144 data_pos = 0; |
12848 } | 13145 } |
12849 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); | 13146 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); |
(...skipping 24 matching lines...) Expand all Loading... | |
12874 class_ids->Clear(); | 13171 class_ids->Clear(); |
12875 const Array& data = Array::Handle(ic_data()); | 13172 const Array& data = Array::Handle(ic_data()); |
12876 intptr_t data_pos = index * TestEntryLength(); | 13173 intptr_t data_pos = index * TestEntryLength(); |
12877 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 13174 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
12878 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); | 13175 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); |
12879 } | 13176 } |
12880 (*target) ^= data.At(data_pos++); | 13177 (*target) ^= data.At(data_pos++); |
12881 } | 13178 } |
12882 | 13179 |
12883 | 13180 |
13181 bool ICData::IsSentinelAt(intptr_t index) const { | |
13182 ASSERT(index < Length()); | |
13183 const Array& data = Array::Handle(ic_data()); | |
13184 const intptr_t entry_length = TestEntryLength(); | |
13185 intptr_t data_pos = index * TestEntryLength(); | |
13186 for (intptr_t i = 0; i < entry_length; i++) { | |
13187 if (data.At(data_pos++) != smi_illegal_cid().raw()) { | |
13188 return false; | |
13189 } | |
13190 } | |
13191 // The entry at |index| was filled with the value kIllegalCid. | |
13192 return true; | |
13193 } | |
13194 | |
13195 | |
12884 void ICData::GetClassIdsAt(intptr_t index, | 13196 void ICData::GetClassIdsAt(intptr_t index, |
12885 GrowableArray<intptr_t>* class_ids) const { | 13197 GrowableArray<intptr_t>* class_ids) const { |
12886 ASSERT(index < NumberOfChecks()); | 13198 ASSERT(index < Length()); |
12887 ASSERT(class_ids != NULL); | 13199 ASSERT(class_ids != NULL); |
13200 ASSERT(!IsSentinelAt(index)); | |
12888 class_ids->Clear(); | 13201 class_ids->Clear(); |
12889 const Array& data = Array::Handle(ic_data()); | 13202 const Array& data = Array::Handle(ic_data()); |
12890 intptr_t data_pos = index * TestEntryLength(); | 13203 intptr_t data_pos = index * TestEntryLength(); |
12891 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 13204 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
12892 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); | 13205 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); |
12893 } | 13206 } |
12894 } | 13207 } |
12895 | 13208 |
12896 | 13209 |
12897 void ICData::GetOneClassCheckAt(intptr_t index, | 13210 void ICData::GetOneClassCheckAt(intptr_t index, |
(...skipping 18 matching lines...) Expand all Loading... | |
12916 | 13229 |
12917 | 13230 |
12918 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { | 13231 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { |
12919 GrowableArray<intptr_t> class_ids; | 13232 GrowableArray<intptr_t> class_ids; |
12920 GetClassIdsAt(index, &class_ids); | 13233 GetClassIdsAt(index, &class_ids); |
12921 return class_ids[arg_nr]; | 13234 return class_ids[arg_nr]; |
12922 } | 13235 } |
12923 | 13236 |
12924 | 13237 |
12925 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { | 13238 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { |
12926 ASSERT(index < NumberOfChecks()); | 13239 ASSERT(index < Length()); |
13240 ASSERT(!IsSentinelAt(index)); | |
12927 const intptr_t data_pos = index * TestEntryLength(); | 13241 const intptr_t data_pos = index * TestEntryLength(); |
12928 NoSafepointScope no_safepoint; | 13242 NoSafepointScope no_safepoint; |
12929 RawArray* raw_data = ic_data(); | 13243 RawArray* raw_data = ic_data(); |
12930 return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos])); | 13244 return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos])); |
12931 } | 13245 } |
12932 | 13246 |
12933 | 13247 |
12934 RawFunction* ICData::GetTargetAt(intptr_t index) const { | 13248 RawFunction* ICData::GetTargetAt(intptr_t index) const { |
12935 ASSERT(Isolate::Current()->compilation_allowed()); | 13249 ASSERT(Isolate::Current()->compilation_allowed()); |
12936 const intptr_t data_pos = index * TestEntryLength() + NumArgsTested(); | 13250 const intptr_t data_pos = index * TestEntryLength() + NumArgsTested(); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13120 &Function::ZoneHandle(GetTargetAt(i)))); | 13434 &Function::ZoneHandle(GetTargetAt(i)))); |
13121 } | 13435 } |
13122 } | 13436 } |
13123 aggregate.Sort(CidCount::HighestCountFirst); | 13437 aggregate.Sort(CidCount::HighestCountFirst); |
13124 | 13438 |
13125 ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested)); | 13439 ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested)); |
13126 ASSERT(result.NumberOfChecks() == 0); | 13440 ASSERT(result.NumberOfChecks() == 0); |
13127 // Room for all entries and the sentinel. | 13441 // Room for all entries and the sentinel. |
13128 const intptr_t data_len = | 13442 const intptr_t data_len = |
13129 result.TestEntryLength() * (aggregate.length() + 1); | 13443 result.TestEntryLength() * (aggregate.length() + 1); |
13444 // Allocate the array but do not assign it to result until we have populated | |
13445 // it with the aggregate data and the terminating sentinel. | |
13130 const Array& data = Array::Handle(Array::New(data_len, Heap::kOld)); | 13446 const Array& data = Array::Handle(Array::New(data_len, Heap::kOld)); |
13131 result.set_ic_data_array(data); | |
13132 ASSERT(result.NumberOfChecks() == aggregate.length()); | |
13133 | |
13134 intptr_t pos = 0; | 13447 intptr_t pos = 0; |
13135 for (intptr_t i = 0; i < aggregate.length(); i++) { | 13448 for (intptr_t i = 0; i < aggregate.length(); i++) { |
13136 data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid))); | 13449 data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid))); |
13137 data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function); | 13450 data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function); |
13138 data.SetAt(pos + CountIndexFor(1), | 13451 data.SetAt(pos + CountIndexFor(1), |
13139 Smi::Handle(Smi::New(aggregate[i].count))); | 13452 Smi::Handle(Smi::New(aggregate[i].count))); |
13140 | 13453 |
13141 pos += result.TestEntryLength(); | 13454 pos += result.TestEntryLength(); |
13142 } | 13455 } |
13143 WriteSentinel(data, result.TestEntryLength()); | 13456 WriteSentinel(data, result.TestEntryLength()); |
13144 result.set_ic_data_array(data); | 13457 result.set_ic_data_array(data); |
13458 ASSERT(result.NumberOfChecks() == aggregate.length()); | |
13145 return result.raw(); | 13459 return result.raw(); |
13146 } | 13460 } |
13147 | 13461 |
13148 | 13462 |
13149 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { | 13463 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { |
13150 if (NumberOfChecks() == 0) return false; | 13464 if (NumberOfChecks() == 0) return false; |
13151 Class& cls = Class::Handle(); | 13465 Class& cls = Class::Handle(); |
13152 const intptr_t len = NumberOfChecks(); | 13466 const intptr_t len = NumberOfChecks(); |
13153 for (intptr_t i = 0; i < len; i++) { | 13467 for (intptr_t i = 0; i < len; i++) { |
13154 if (IsUsedAt(i)) { | 13468 if (IsUsedAt(i)) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13281 result.set_deopt_id(deopt_id); | 13595 result.set_deopt_id(deopt_id); |
13282 result.set_state_bits(0); | 13596 result.set_state_bits(0); |
13283 #if defined(TAG_IC_DATA) | 13597 #if defined(TAG_IC_DATA) |
13284 result.set_tag(-1); | 13598 result.set_tag(-1); |
13285 #endif | 13599 #endif |
13286 result.SetNumArgsTested(num_args_tested); | 13600 result.SetNumArgsTested(num_args_tested); |
13287 return result.raw(); | 13601 return result.raw(); |
13288 } | 13602 } |
13289 | 13603 |
13290 | 13604 |
13605 bool ICData::IsImmutable() const { | |
13606 const Array& data = Array::Handle(ic_data()); | |
13607 return data.IsImmutable(); | |
13608 } | |
13609 | |
13610 | |
13611 void ICData::ResetData() const { | |
13612 // Number of array elements in one test entry. | |
13613 intptr_t len = TestEntryLength(); | |
13614 // IC data array must be null terminated (sentinel entry). | |
13615 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); | |
13616 set_ic_data_array(ic_data); | |
13617 WriteSentinel(ic_data, len); | |
13618 } | |
13619 | |
13620 | |
13291 RawICData* ICData::New() { | 13621 RawICData* ICData::New() { |
13292 ICData& result = ICData::Handle(); | 13622 ICData& result = ICData::Handle(); |
13293 { | 13623 { |
13294 // IC data objects are long living objects, allocate them in old generation. | 13624 // IC data objects are long living objects, allocate them in old generation. |
13295 RawObject* raw = Object::Allocate(ICData::kClassId, | 13625 RawObject* raw = Object::Allocate(ICData::kClassId, |
13296 ICData::InstanceSize(), | 13626 ICData::InstanceSize(), |
13297 Heap::kOld); | 13627 Heap::kOld); |
13298 NoSafepointScope no_safepoint; | 13628 NoSafepointScope no_safepoint; |
13299 result ^= raw; | 13629 result ^= raw; |
13300 } | 13630 } |
(...skipping 2303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15604 } | 15934 } |
15605 | 15935 |
15606 | 15936 |
15607 bool AbstractType::HasResolvedTypeClass() const { | 15937 bool AbstractType::HasResolvedTypeClass() const { |
15608 // AbstractType is an abstract class. | 15938 // AbstractType is an abstract class. |
15609 UNREACHABLE(); | 15939 UNREACHABLE(); |
15610 return false; | 15940 return false; |
15611 } | 15941 } |
15612 | 15942 |
15613 | 15943 |
15944 classid_t AbstractType::type_class_id() const { | |
15945 // AbstractType is an abstract class. | |
15946 UNREACHABLE(); | |
15947 return kIllegalCid; | |
15948 } | |
15949 | |
15950 | |
15614 RawClass* AbstractType::type_class() const { | 15951 RawClass* AbstractType::type_class() const { |
15615 // AbstractType is an abstract class. | 15952 // AbstractType is an abstract class. |
15616 UNREACHABLE(); | 15953 UNREACHABLE(); |
15617 return Class::null(); | 15954 return Class::null(); |
15618 } | 15955 } |
15619 | 15956 |
15620 | 15957 |
15621 RawUnresolvedClass* AbstractType::unresolved_class() const { | 15958 RawUnresolvedClass* AbstractType::unresolved_class() const { |
15622 // AbstractType is an abstract class. | 15959 // AbstractType is an abstract class. |
15623 UNREACHABLE(); | 15960 UNREACHABLE(); |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16469 } | 16806 } |
16470 | 16807 |
16471 | 16808 |
16472 void Type::SetIsResolved() const { | 16809 void Type::SetIsResolved() const { |
16473 ASSERT(!IsResolved()); | 16810 ASSERT(!IsResolved()); |
16474 set_type_state(RawType::kResolved); | 16811 set_type_state(RawType::kResolved); |
16475 } | 16812 } |
16476 | 16813 |
16477 | 16814 |
16478 bool Type::HasResolvedTypeClass() const { | 16815 bool Type::HasResolvedTypeClass() const { |
16479 return (raw_ptr()->type_class_->GetClassId() == kClassCid); | 16816 return !raw_ptr()->type_class_id_->IsHeapObject(); |
16817 } | |
16818 | |
16819 | |
16820 classid_t Type::type_class_id() const { | |
16821 ASSERT(HasResolvedTypeClass()); | |
16822 return Smi::Value(reinterpret_cast<RawSmi*>(raw_ptr()->type_class_id_)); | |
16480 } | 16823 } |
16481 | 16824 |
16482 | 16825 |
16483 RawClass* Type::type_class() const { | 16826 RawClass* Type::type_class() const { |
16484 #ifdef DEBUG | 16827 return Isolate::Current()->class_table()->At(type_class_id()); |
16485 ASSERT(HasResolvedTypeClass()); | |
16486 Class& type_class = Class::Handle(); | |
16487 type_class ^= raw_ptr()->type_class_; | |
16488 return type_class.raw(); | |
16489 #else | |
16490 return reinterpret_cast<RawClass*>(raw_ptr()->type_class_); | |
16491 #endif | |
16492 } | 16828 } |
16493 | 16829 |
16494 | 16830 |
16495 RawUnresolvedClass* Type::unresolved_class() const { | 16831 RawUnresolvedClass* Type::unresolved_class() const { |
16496 #ifdef DEBUG | 16832 #ifdef DEBUG |
16497 ASSERT(!HasResolvedTypeClass()); | 16833 ASSERT(!HasResolvedTypeClass()); |
16498 UnresolvedClass& unresolved_class = UnresolvedClass::Handle(); | 16834 UnresolvedClass& unresolved_class = UnresolvedClass::Handle(); |
16499 unresolved_class ^= raw_ptr()->type_class_; | 16835 unresolved_class ^= raw_ptr()->type_class_id_; |
16500 ASSERT(!unresolved_class.IsNull()); | 16836 ASSERT(!unresolved_class.IsNull()); |
16501 return unresolved_class.raw(); | 16837 return unresolved_class.raw(); |
16502 #else | 16838 #else |
16503 ASSERT(!Object::Handle(raw_ptr()->type_class_).IsNull()); | 16839 ASSERT(!Object::Handle(raw_ptr()->type_class_id_).IsNull()); |
16504 ASSERT(Object::Handle(raw_ptr()->type_class_).IsUnresolvedClass()); | 16840 ASSERT(Object::Handle(raw_ptr()->type_class_id_).IsUnresolvedClass()); |
16505 return reinterpret_cast<RawUnresolvedClass*>(raw_ptr()->type_class_); | 16841 return reinterpret_cast<RawUnresolvedClass*>(raw_ptr()->type_class_id_); |
16506 #endif | 16842 #endif |
16507 } | 16843 } |
16508 | 16844 |
16509 | 16845 |
16510 bool Type::IsInstantiated(TrailPtr trail) const { | 16846 bool Type::IsInstantiated(TrailPtr trail) const { |
16511 if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) { | 16847 if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) { |
16512 return true; | 16848 return true; |
16513 } | 16849 } |
16514 if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) { | 16850 if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) { |
16515 return false; | 16851 return false; |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17061 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { | 17397 for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) { |
17062 param_name = sig_fun.ParameterNameAt(i); | 17398 param_name = sig_fun.ParameterNameAt(i); |
17063 result = CombineHashes(result, param_name.Hash()); | 17399 result = CombineHashes(result, param_name.Hash()); |
17064 } | 17400 } |
17065 } | 17401 } |
17066 } | 17402 } |
17067 return FinalizeHash(result); | 17403 return FinalizeHash(result); |
17068 } | 17404 } |
17069 | 17405 |
17070 | 17406 |
17071 void Type::set_type_class(const Object& value) const { | 17407 void Type::set_type_class(const Class& value) const { |
17072 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass())); | 17408 ASSERT(!value.IsNull()); |
17073 StorePointer(&raw_ptr()->type_class_, value.raw()); | 17409 StorePointer(&raw_ptr()->type_class_id_, |
17410 reinterpret_cast<RawObject*>(Smi::New(value.id()))); | |
17074 } | 17411 } |
17075 | 17412 |
17076 | 17413 |
17414 void Type::set_unresolved_class(const Object& value) const { | |
17415 ASSERT(!value.IsNull() && value.IsUnresolvedClass()); | |
17416 StorePointer(&raw_ptr()->type_class_id_, value.raw()); | |
17417 } | |
17418 | |
17419 | |
17077 void Type::set_arguments(const TypeArguments& value) const { | 17420 void Type::set_arguments(const TypeArguments& value) const { |
17078 ASSERT(!IsCanonical()); | 17421 ASSERT(!IsCanonical()); |
17079 StorePointer(&raw_ptr()->arguments_, value.raw()); | 17422 StorePointer(&raw_ptr()->arguments_, value.raw()); |
17080 } | 17423 } |
17081 | 17424 |
17082 | 17425 |
17083 RawType* Type::New(Heap::Space space) { | 17426 RawType* Type::New(Heap::Space space) { |
17084 RawObject* raw = Object::Allocate(Type::kClassId, | 17427 RawObject* raw = Object::Allocate(Type::kClassId, |
17085 Type::InstanceSize(), | 17428 Type::InstanceSize(), |
17086 space); | 17429 space); |
17087 return reinterpret_cast<RawType*>(raw); | 17430 return reinterpret_cast<RawType*>(raw); |
17088 } | 17431 } |
17089 | 17432 |
17090 | 17433 |
17091 RawType* Type::New(const Object& clazz, | 17434 RawType* Type::New(const Object& clazz, |
17092 const TypeArguments& arguments, | 17435 const TypeArguments& arguments, |
17093 TokenPosition token_pos, | 17436 TokenPosition token_pos, |
17094 Heap::Space space) { | 17437 Heap::Space space) { |
17095 const Type& result = Type::Handle(Type::New(space)); | 17438 const Type& result = Type::Handle(Type::New(space)); |
17096 result.set_type_class(clazz); | 17439 if (clazz.IsClass()) { |
17440 result.set_type_class(Class::Cast(clazz)); | |
17441 } else { | |
17442 result.set_unresolved_class(clazz); | |
17443 } | |
17097 result.set_arguments(arguments); | 17444 result.set_arguments(arguments); |
17098 result.set_token_pos(token_pos); | 17445 result.set_token_pos(token_pos); |
17099 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); | 17446 result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated); |
17100 return result.raw(); | 17447 return result.raw(); |
17101 } | 17448 } |
17102 | 17449 |
17103 | 17450 |
17104 void Type::set_token_pos(TokenPosition token_pos) const { | 17451 void Type::set_token_pos(TokenPosition token_pos) const { |
17105 ASSERT(!token_pos.IsClassifying()); | 17452 ASSERT(!token_pos.IsClassifying()); |
17106 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); | 17453 StoreNonPointer(&raw_ptr()->token_pos_, token_pos); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17334 } | 17681 } |
17335 if (IsFinalized() == other_type_param.IsFinalized()) { | 17682 if (IsFinalized() == other_type_param.IsFinalized()) { |
17336 return index() == other_type_param.index(); | 17683 return index() == other_type_param.index(); |
17337 } | 17684 } |
17338 return name() == other_type_param.name(); | 17685 return name() == other_type_param.name(); |
17339 } | 17686 } |
17340 | 17687 |
17341 | 17688 |
17342 void TypeParameter::set_parameterized_class(const Class& value) const { | 17689 void TypeParameter::set_parameterized_class(const Class& value) const { |
17343 // Set value may be null. | 17690 // Set value may be null. |
17344 StorePointer(&raw_ptr()->parameterized_class_, value.raw()); | 17691 classid_t cid = kIllegalCid; |
17692 if (!value.IsNull()) { | |
17693 cid = value.id(); | |
17694 } | |
17695 StoreNonPointer(&raw_ptr()->parameterized_class_id_, cid); | |
17345 } | 17696 } |
17346 | 17697 |
17347 | 17698 |
17699 classid_t TypeParameter::parameterized_class_id() const { | |
17700 return raw_ptr()->parameterized_class_id_; | |
17701 } | |
17702 | |
17703 | |
17704 RawClass* TypeParameter::parameterized_class() const { | |
17705 classid_t cid = parameterized_class_id(); | |
17706 if (cid == kIllegalCid) { | |
17707 return Class::null(); | |
17708 } | |
17709 return Isolate::Current()->class_table()->At(cid); | |
17710 } | |
17711 | |
17712 | |
17348 void TypeParameter::set_index(intptr_t value) const { | 17713 void TypeParameter::set_index(intptr_t value) const { |
17349 ASSERT(value >= 0); | 17714 ASSERT(value >= 0); |
17350 ASSERT(Utils::IsInt(16, value)); | 17715 ASSERT(Utils::IsInt(16, value)); |
17351 StoreNonPointer(&raw_ptr()->index_, value); | 17716 StoreNonPointer(&raw_ptr()->index_, value); |
17352 } | 17717 } |
17353 | 17718 |
17354 | 17719 |
17355 void TypeParameter::set_name(const String& value) const { | 17720 void TypeParameter::set_name(const String& value) const { |
17356 ASSERT(value.IsSymbol()); | 17721 ASSERT(value.IsSymbol()); |
17357 StorePointer(&raw_ptr()->name_, value.raw()); | 17722 StorePointer(&raw_ptr()->name_, value.raw()); |
(...skipping 5099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
22457 return UserTag::null(); | 22822 return UserTag::null(); |
22458 } | 22823 } |
22459 | 22824 |
22460 | 22825 |
22461 const char* UserTag::ToCString() const { | 22826 const char* UserTag::ToCString() const { |
22462 const String& tag_label = String::Handle(label()); | 22827 const String& tag_label = String::Handle(label()); |
22463 return tag_label.ToCString(); | 22828 return tag_label.ToCString(); |
22464 } | 22829 } |
22465 | 22830 |
22466 } // namespace dart | 22831 } // namespace dart |
OLD | NEW |