| 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 |