Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: runtime/vm/object.cc

Issue 1410363005: Make ICData changes thread safe (first compute array, then set it). Install code in the main thread… (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Address comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/regexp_assembler_ir.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 5364 matching lines...) Expand 10 before | Expand all | Expand 10 after
5375 void PatchClass::set_source_class(const Class& value) const { 5375 void PatchClass::set_source_class(const Class& value) const {
5376 StorePointer(&raw_ptr()->source_class_, value.raw()); 5376 StorePointer(&raw_ptr()->source_class_, value.raw());
5377 } 5377 }
5378 5378
5379 5379
5380 bool Function::HasBreakpoint() const { 5380 bool Function::HasBreakpoint() const {
5381 return Isolate::Current()->debugger()->HasBreakpoint(*this); 5381 return Isolate::Current()->debugger()->HasBreakpoint(*this);
5382 } 5382 }
5383 5383
5384 5384
5385 void Function::InstallOptimizedCode(const Code& code, bool is_osr) const {
5386 // We may not have previous code if 'always_optimize' is set.
5387 if (!is_osr && HasCode()) {
5388 Code::Handle(CurrentCode()).DisableDartCode();
5389 }
5390 AttachCode(code);
5391 }
5392
5393
5385 void Function::SetInstructions(const Code& value) const { 5394 void Function::SetInstructions(const Code& value) const {
5395 ASSERT(Thread::Current()->IsMutatorThread());
5396 SetInstructionsSafe(value);
5397 }
5398
5399
5400 void Function::SetInstructionsSafe(const Code& value) const {
5386 StorePointer(&raw_ptr()->code_, value.raw()); 5401 StorePointer(&raw_ptr()->code_, value.raw());
5387 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint()); 5402 StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint());
5388 } 5403 }
5389 5404
5405
5390 void Function::AttachCode(const Code& value) const { 5406 void Function::AttachCode(const Code& value) const {
5391 // Finish setting up code before activating it. 5407 // Finish setting up code before activating it.
5392 value.set_owner(*this); 5408 value.set_owner(*this);
5393 SetInstructions(value); 5409 SetInstructions(value);
5394 ASSERT(Function::Handle(value.function()).IsNull() || 5410 ASSERT(Function::Handle(value.function()).IsNull() ||
5395 (value.function() == this->raw())); 5411 (value.function() == this->raw()));
5396 } 5412 }
5397 5413
5398 5414
5399 bool Function::HasCode() const { 5415 bool Function::HasCode() const {
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after
6485 result.set_num_fixed_parameters(0); 6501 result.set_num_fixed_parameters(0);
6486 result.set_num_optional_parameters(0); 6502 result.set_num_optional_parameters(0);
6487 result.set_usage_counter(0); 6503 result.set_usage_counter(0);
6488 result.set_deoptimization_counter(0); 6504 result.set_deoptimization_counter(0);
6489 result.set_optimized_instruction_count(0); 6505 result.set_optimized_instruction_count(0);
6490 result.set_optimized_call_site_count(0); 6506 result.set_optimized_call_site_count(0);
6491 result.set_is_optimizable(is_native ? false : true); 6507 result.set_is_optimizable(is_native ? false : true);
6492 result.set_is_inlinable(true); 6508 result.set_is_inlinable(true);
6493 result.set_allows_hoisting_check_class(true); 6509 result.set_allows_hoisting_check_class(true);
6494 result.set_allows_bounds_check_generalization(true); 6510 result.set_allows_bounds_check_generalization(true);
6495 result.SetInstructions(Code::Handle(StubCode::LazyCompile_entry()->code())); 6511 result.SetInstructionsSafe(
6512 Code::Handle(StubCode::LazyCompile_entry()->code()));
6496 if (kind == RawFunction::kClosureFunction) { 6513 if (kind == RawFunction::kClosureFunction) {
6497 const ClosureData& data = ClosureData::Handle(ClosureData::New()); 6514 const ClosureData& data = ClosureData::Handle(ClosureData::New());
6498 result.set_data(data); 6515 result.set_data(data);
6499 } 6516 }
6500 return result.raw(); 6517 return result.raw();
6501 } 6518 }
6502 6519
6503 6520
6504 RawFunction* Function::Clone(const Class& new_owner) const { 6521 RawFunction* Function::Clone(const Class& new_owner) const {
6505 ASSERT(!IsGenerativeConstructor()); 6522 ASSERT(!IsGenerativeConstructor());
(...skipping 5571 matching lines...) Expand 10 before | Expand all | Expand 10 after
12077 ASSERT(!value.IsNull()); 12094 ASSERT(!value.IsNull());
12078 StorePointer(&raw_ptr()->args_descriptor_, value.raw()); 12095 StorePointer(&raw_ptr()->args_descriptor_, value.raw());
12079 } 12096 }
12080 12097
12081 void ICData::set_deopt_id(intptr_t value) const { 12098 void ICData::set_deopt_id(intptr_t value) const {
12082 ASSERT(value <= kMaxInt32); 12099 ASSERT(value <= kMaxInt32);
12083 StoreNonPointer(&raw_ptr()->deopt_id_, value); 12100 StoreNonPointer(&raw_ptr()->deopt_id_, value);
12084 } 12101 }
12085 12102
12086 12103
12087 void ICData::set_ic_data(const Array& value) const { 12104 void ICData::set_ic_data_array(const Array& value) const {
12088 ASSERT(!value.IsNull()); 12105 ASSERT(!value.IsNull());
12089 StorePointer(&raw_ptr()->ic_data_, value.raw()); 12106 StorePointer(&raw_ptr()->ic_data_, value.raw());
12090 } 12107 }
12091 12108
12092 12109
12093 intptr_t ICData::NumArgsTested() const { 12110 intptr_t ICData::NumArgsTested() const {
12094 return NumArgsTestedBits::decode(raw_ptr()->state_bits_); 12111 return NumArgsTestedBits::decode(raw_ptr()->state_bits_);
12095 } 12112 }
12096 12113
12097 12114
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
12185 intptr_t count = 0; 12202 intptr_t count = 0;
12186 for (intptr_t i = 0; i < n; i++) { 12203 for (intptr_t i = 0; i < n; i++) {
12187 if (GetCountAt(i) > 0) { 12204 if (GetCountAt(i) > 0) {
12188 count++; 12205 count++;
12189 } 12206 }
12190 } 12207 }
12191 return count; 12208 return count;
12192 } 12209 }
12193 12210
12194 12211
12195 void ICData::WriteSentinel(const Array& data) const { 12212 void ICData::WriteSentinel(const Array& data, intptr_t test_entry_length) {
12196 ASSERT(!data.IsNull()); 12213 ASSERT(!data.IsNull());
12197 for (intptr_t i = 1; i <= TestEntryLength(); i++) { 12214 for (intptr_t i = 1; i <= test_entry_length; i++) {
12198 data.SetAt(data.Length() - i, smi_illegal_cid()); 12215 data.SetAt(data.Length() - i, smi_illegal_cid());
12199 } 12216 }
12200 } 12217 }
12201 12218
12202 12219
12203 #if defined(DEBUG) 12220 #if defined(DEBUG)
12204 // Used in asserts to verify that a check is not added twice. 12221 // Used in asserts to verify that a check is not added twice.
12205 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const { 12222 bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const {
12206 const intptr_t len = NumberOfChecks(); 12223 const intptr_t len = NumberOfChecks();
12207 for (intptr_t i = 0; i < len; i++) { 12224 for (intptr_t i = 0; i < len; i++) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
12240 } 12257 }
12241 return; 12258 return;
12242 } 12259 }
12243 ASSERT(NumArgsTested() == 0); 12260 ASSERT(NumArgsTested() == 0);
12244 // Can add only once. 12261 // Can add only once.
12245 const intptr_t old_num = NumberOfChecks(); 12262 const intptr_t old_num = NumberOfChecks();
12246 ASSERT(old_num == 0); 12263 ASSERT(old_num == 0);
12247 Array& data = Array::Handle(ic_data()); 12264 Array& data = Array::Handle(ic_data());
12248 const intptr_t new_len = data.Length() + TestEntryLength(); 12265 const intptr_t new_len = data.Length() + TestEntryLength();
12249 data = Array::Grow(data, new_len, Heap::kOld); 12266 data = Array::Grow(data, new_len, Heap::kOld);
12250 set_ic_data(data); 12267 WriteSentinel(data, TestEntryLength());
12251 WriteSentinel(data);
12252 intptr_t data_pos = old_num * TestEntryLength(); 12268 intptr_t data_pos = old_num * TestEntryLength();
12253 ASSERT(!target.IsNull()); 12269 ASSERT(!target.IsNull());
12254 data.SetAt(data_pos++, target); 12270 data.SetAt(data_pos++, target);
12255 // Set count to 0 as this is called during compilation, before the 12271 // Set count to 0 as this is called during compilation, before the
12256 // call has been executed. 12272 // call has been executed.
12257 const Smi& value = Smi::Handle(Smi::New(0)); 12273 const Smi& value = Smi::Handle(Smi::New(0));
12258 data.SetAt(data_pos, value); 12274 data.SetAt(data_pos, value);
12275 // Multithreaded access to ICData requires setting of array to be the last
12276 // operation.
12277 set_ic_data_array(data);
12259 } 12278 }
12260 12279
12261 12280
12262 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, 12281 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids,
12263 const Function& target) const { 12282 const Function& target) const {
12264 ASSERT(!target.IsNull()); 12283 ASSERT(!target.IsNull());
12265 ASSERT(target.name() == target_name()); 12284 ASSERT(target.name() == target_name());
12266 DEBUG_ASSERT(!HasCheck(class_ids)); 12285 DEBUG_ASSERT(!HasCheck(class_ids));
12267 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. 12286 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'.
12268 ASSERT(class_ids.length() == NumArgsTested()); 12287 ASSERT(class_ids.length() == NumArgsTested());
(...skipping 17 matching lines...) Expand all
12286 for (intptr_t i = 0; i < NumArgsTested(); i++) { 12305 for (intptr_t i = 0; i < NumArgsTested(); i++) {
12287 ASSERT(class_ids[i] != kIllegalCid); 12306 ASSERT(class_ids[i] != kIllegalCid);
12288 value = Smi::New(class_ids[i]); 12307 value = Smi::New(class_ids[i]);
12289 data.SetAt(i, value); 12308 data.SetAt(i, value);
12290 } 12309 }
12291 return; 12310 return;
12292 } 12311 }
12293 } 12312 }
12294 const intptr_t new_len = data.Length() + TestEntryLength(); 12313 const intptr_t new_len = data.Length() + TestEntryLength();
12295 data = Array::Grow(data, new_len, Heap::kOld); 12314 data = Array::Grow(data, new_len, Heap::kOld);
12296 set_ic_data(data); 12315 WriteSentinel(data, TestEntryLength());
12297 WriteSentinel(data);
12298 intptr_t data_pos = old_num * TestEntryLength(); 12316 intptr_t data_pos = old_num * TestEntryLength();
12299 Smi& value = Smi::Handle(); 12317 Smi& value = Smi::Handle();
12300 for (intptr_t i = 0; i < class_ids.length(); i++) { 12318 for (intptr_t i = 0; i < class_ids.length(); i++) {
12301 // kIllegalCid is used as terminating value, do not add it. 12319 // kIllegalCid is used as terminating value, do not add it.
12302 ASSERT(class_ids[i] != kIllegalCid); 12320 ASSERT(class_ids[i] != kIllegalCid);
12303 value = Smi::New(class_ids[i]); 12321 value = Smi::New(class_ids[i]);
12304 data.SetAt(data_pos++, value); 12322 data.SetAt(data_pos++, value);
12305 } 12323 }
12306 ASSERT(!target.IsNull()); 12324 ASSERT(!target.IsNull());
12307 data.SetAt(data_pos++, target); 12325 data.SetAt(data_pos++, target);
12308 value = Smi::New(1); 12326 value = Smi::New(1);
12309 data.SetAt(data_pos, value); 12327 data.SetAt(data_pos, value);
12328 // Multithreaded access to ICData requires setting of array to be the last
12329 // operation.
12330 set_ic_data_array(data);
12310 } 12331 }
12311 12332
12312 12333
12313 void ICData::AddReceiverCheck(intptr_t receiver_class_id, 12334 void ICData::AddReceiverCheck(intptr_t receiver_class_id,
12314 const Function& target, 12335 const Function& target,
12315 intptr_t count) const { 12336 intptr_t count) const {
12316 #if defined(DEBUG) 12337 #if defined(DEBUG)
12317 GrowableArray<intptr_t> class_ids(1); 12338 GrowableArray<intptr_t> class_ids(1);
12318 class_ids.Add(receiver_class_id); 12339 class_ids.Add(receiver_class_id);
12319 ASSERT(!HasCheck(class_ids)); 12340 ASSERT(!HasCheck(class_ids));
12320 #endif // DEBUG 12341 #endif // DEBUG
12321 ASSERT(!target.IsNull()); 12342 ASSERT(!target.IsNull());
12322 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. 12343 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'.
12323 ASSERT(receiver_class_id != kIllegalCid); 12344 ASSERT(receiver_class_id != kIllegalCid);
12324 12345
12325 const intptr_t old_num = NumberOfChecks(); 12346 const intptr_t old_num = NumberOfChecks();
12326 Array& data = Array::Handle(ic_data()); 12347 Array& data = Array::Handle(ic_data());
12327 const intptr_t new_len = data.Length() + TestEntryLength(); 12348 const intptr_t new_len = data.Length() + TestEntryLength();
12328 data = Array::Grow(data, new_len, Heap::kOld); 12349 data = Array::Grow(data, new_len, Heap::kOld);
12329 set_ic_data(data); 12350 WriteSentinel(data, TestEntryLength());
12330 WriteSentinel(data);
12331 intptr_t data_pos = old_num * TestEntryLength(); 12351 intptr_t data_pos = old_num * TestEntryLength();
12332 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { 12352 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) {
12333 ASSERT(GetReceiverClassIdAt(0) != kSmiCid); 12353 ASSERT(GetReceiverClassIdAt(0) != kSmiCid);
12334 // Move class occupying position 0 to the data_pos. 12354 // Move class occupying position 0 to the data_pos.
12335 for (intptr_t i = 0; i < TestEntryLength(); i++) { 12355 for (intptr_t i = 0; i < TestEntryLength(); i++) {
12336 data.SetAt(data_pos + i, Object::Handle(data.At(i))); 12356 data.SetAt(data_pos + i, Object::Handle(data.At(i)));
12337 } 12357 }
12338 // Insert kSmiCid in position 0. 12358 // Insert kSmiCid in position 0.
12339 data_pos = 0; 12359 data_pos = 0;
12340 } 12360 }
12341 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id))); 12361 data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id)));
12342 data.SetAt(data_pos + 1, target); 12362 data.SetAt(data_pos + 1, target);
12343 data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count))); 12363 data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
12364 // Multithreaded access to ICData requires setting of array to be the last
12365 // operation.
12366 set_ic_data_array(data);
12344 } 12367 }
12345 12368
12346 12369
12347 void ICData::GetCheckAt(intptr_t index, 12370 void ICData::GetCheckAt(intptr_t index,
12348 GrowableArray<intptr_t>* class_ids, 12371 GrowableArray<intptr_t>* class_ids,
12349 Function* target) const { 12372 Function* target) const {
12350 ASSERT(index < NumberOfChecks()); 12373 ASSERT(index < NumberOfChecks());
12351 ASSERT(class_ids != NULL); 12374 ASSERT(class_ids != NULL);
12352 ASSERT(target != NULL); 12375 ASSERT(target != NULL);
12353 class_ids->Clear(); 12376 class_ids->Clear();
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
12629 result.set_owner(owner); 12652 result.set_owner(owner);
12630 result.set_target_name(target_name); 12653 result.set_target_name(target_name);
12631 result.set_arguments_descriptor(arguments_descriptor); 12654 result.set_arguments_descriptor(arguments_descriptor);
12632 result.set_deopt_id(deopt_id); 12655 result.set_deopt_id(deopt_id);
12633 result.set_state_bits(0); 12656 result.set_state_bits(0);
12634 result.SetNumArgsTested(num_args_tested); 12657 result.SetNumArgsTested(num_args_tested);
12635 // Number of array elements in one test entry. 12658 // Number of array elements in one test entry.
12636 intptr_t len = result.TestEntryLength(); 12659 intptr_t len = result.TestEntryLength();
12637 // IC data array must be null terminated (sentinel entry). 12660 // IC data array must be null terminated (sentinel entry).
12638 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); 12661 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld));
12639 result.set_ic_data(ic_data); 12662 WriteSentinel(ic_data, result.TestEntryLength());
12640 result.WriteSentinel(ic_data); 12663 result.set_ic_data_array(ic_data);
12641 return result.raw(); 12664 return result.raw();
12642 } 12665 }
12643 12666
12644 12667
12645 RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) { 12668 RawICData* ICData::NewFrom(const ICData& from, intptr_t num_args_tested) {
12646 const ICData& result = ICData::Handle(ICData::New( 12669 const ICData& result = ICData::Handle(ICData::New(
12647 Function::Handle(from.owner()), 12670 Function::Handle(from.owner()),
12648 String::Handle(from.target_name()), 12671 String::Handle(from.target_name()),
12649 Array::Handle(from.arguments_descriptor()), 12672 Array::Handle(from.arguments_descriptor()),
12650 from.deopt_id(), 12673 from.deopt_id(),
(...skipping 9105 matching lines...) Expand 10 before | Expand all | Expand 10 after
21756 return tag_label.ToCString(); 21779 return tag_label.ToCString();
21757 } 21780 }
21758 21781
21759 21782
21760 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 21783 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
21761 Instance::PrintJSONImpl(stream, ref); 21784 Instance::PrintJSONImpl(stream, ref);
21762 } 21785 }
21763 21786
21764 21787
21765 } // namespace dart 21788 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/regexp_assembler_ir.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698