Chromium Code Reviews

Side by Side Diff: src/IceGlobalContext.cpp

Issue 848193003: Subzero: Add locking to prepare for multithreaded translation. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Code review changes Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===// 1 //===- subzero/src/IceGlobalContext.cpp - Global context defs -------------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file defines aspects of the compilation that persist across 10 // This file defines aspects of the compilation that persist across
(...skipping 90 matching lines...)
101 TypePool<IceType_f64, double, ConstantDouble> Doubles; 101 TypePool<IceType_f64, double, ConstantDouble> Doubles;
102 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1; 102 TypePool<IceType_i1, int8_t, ConstantInteger32> Integers1;
103 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8; 103 TypePool<IceType_i8, int8_t, ConstantInteger32> Integers8;
104 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16; 104 TypePool<IceType_i16, int16_t, ConstantInteger32> Integers16;
105 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32; 105 TypePool<IceType_i32, int32_t, ConstantInteger32> Integers32;
106 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64; 106 TypePool<IceType_i64, int64_t, ConstantInteger64> Integers64;
107 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables; 107 TypePool<IceType_i32, RelocatableTuple, ConstantRelocatable> Relocatables;
108 UndefPool Undefs; 108 UndefPool Undefs;
109 }; 109 };
110 110
111 void CodeStats::dump(const IceString &Name, Ostream &Str) { 111 void GlobalContext::CodeStats::dump(const IceString &Name, Ostream &Str) {
112 if (!ALLOW_DUMP) 112 if (!ALLOW_DUMP)
113 return; 113 return;
114 Str << "|" << Name << "|Inst Count |" << InstructionsEmitted << "\n"; 114 Str << "|" << Name << "|Inst Count |" << InstructionsEmitted << "\n";
115 Str << "|" << Name << "|Regs Saved |" << RegistersSaved << "\n"; 115 Str << "|" << Name << "|Regs Saved |" << RegistersSaved << "\n";
116 Str << "|" << Name << "|Frame Bytes |" << FrameBytes << "\n"; 116 Str << "|" << Name << "|Frame Bytes |" << FrameBytes << "\n";
117 Str << "|" << Name << "|Spills |" << Spills << "\n"; 117 Str << "|" << Name << "|Spills |" << Spills << "\n";
118 Str << "|" << Name << "|Fills |" << Fills << "\n"; 118 Str << "|" << Name << "|Fills |" << Fills << "\n";
119 Str << "|" << Name << "|Spills+Fills|" << Spills + Fills << "\n"; 119 Str << "|" << Name << "|Spills+Fills|" << Spills + Fills << "\n";
120 Str << "|" << Name << "|Memory Usage|"; 120 Str << "|" << Name << "|Memory Usage|";
121 if (ssize_t MemUsed = llvm::TimeRecord::getCurrentTime(false).getMemUsed()) 121 if (ssize_t MemUsed = llvm::TimeRecord::getCurrentTime(false).getMemUsed())
122 Str << MemUsed; 122 Str << MemUsed;
123 else 123 else
124 Str << "(requires '-track-memory')"; 124 Str << "(requires '-track-memory')";
125 Str << "\n"; 125 Str << "\n";
126 } 126 }
127 127
128 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, 128 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit,
129 ELFStreamer *ELFStr, VerboseMask Mask, 129 ELFStreamer *ELFStr, VerboseMask Mask,
130 TargetArch Arch, OptLevel Opt, 130 TargetArch Arch, OptLevel Opt,
131 IceString TestPrefix, const ClFlags &Flags) 131 IceString TestPrefix, const ClFlags &Flags)
132 : StrDump(OsDump), StrEmit(OsEmit), VMask(Mask), 132 : IsStrLocked(false), StrDump(OsDump), StrEmit(OsEmit), VMask(Mask),
133 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt), 133 ConstPool(new ConstantPool()), Arch(Arch), Opt(Opt),
134 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter() { 134 TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter() {
135 // Create a new ThreadContext for the current thread. No need to
136 // lock AllThreadContexts at this point since no other threads have
137 // access yet to this GlobalContext object.
138 AllThreadContexts.push_back(new ThreadContext());
139 TLS = AllThreadContexts.back();
135 // Pre-register built-in stack names. 140 // Pre-register built-in stack names.
136 if (ALLOW_DUMP) { 141 if (ALLOW_DUMP) {
142 // TODO(stichnot): There needs to be a strong relationship between
143 // the newTimerStackID() return values and TSK_Default/TSK_Funcs.
137 newTimerStackID("Total across all functions"); 144 newTimerStackID("Total across all functions");
138 newTimerStackID("Per-function summary"); 145 newTimerStackID("Per-function summary");
139 } 146 }
140 if (Flags.UseELFWriter) { 147 if (Flags.UseELFWriter) {
141 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr)); 148 ObjectWriter.reset(new ELFObjectWriter(*this, *ELFStr));
142 } 149 }
143 } 150 }
144 151
145 // Scan a string for S[0-9A-Z]*_ patterns and replace them with 152 // Scan a string for S[0-9A-Z]*_ patterns and replace them with
146 // S<num>_ where <num> is the next base-36 value. If a type name 153 // S<num>_ where <num> is the next base-36 value. If a type name
(...skipping 154 matching lines...)
301 return NewName.data(); 308 return NewName.data();
302 } 309 }
303 310
304 // Transform bar ==> Prefixbar 311 // Transform bar ==> Prefixbar
305 // ^^^^^^ 312 // ^^^^^^
306 return getTestPrefix() + Name; 313 return getTestPrefix() + Name;
307 } 314 }
308 315
309 GlobalContext::~GlobalContext() { 316 GlobalContext::~GlobalContext() {
310 llvm::DeleteContainerPointers(GlobalDeclarations); 317 llvm::DeleteContainerPointers(GlobalDeclarations);
318 llvm::DeleteContainerPointers(AllThreadContexts);
311 } 319 }
312 320
321 // TODO(stichnot): Consider adding thread-local caches of constant
322 // pool entries to reduce contention.
323
324 // All locking is done by the getConstantInt[0-9]+() target function.
313 Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) { 325 Constant *GlobalContext::getConstantInt(Type Ty, int64_t Value) {
314 switch (Ty) { 326 switch (Ty) {
315 case IceType_i1: 327 case IceType_i1:
316 return getConstantInt1(Value); 328 return getConstantInt1(Value);
317 case IceType_i8: 329 case IceType_i8:
318 return getConstantInt8(Value); 330 return getConstantInt8(Value);
319 case IceType_i16: 331 case IceType_i16:
320 return getConstantInt16(Value); 332 return getConstantInt16(Value);
321 case IceType_i32: 333 case IceType_i32:
322 return getConstantInt32(Value); 334 return getConstantInt32(Value);
323 case IceType_i64: 335 case IceType_i64:
324 return getConstantInt64(Value); 336 return getConstantInt64(Value);
325 default: 337 default:
326 llvm_unreachable("Bad integer type for getConstant"); 338 llvm_unreachable("Bad integer type for getConstant");
327 } 339 }
328 return nullptr; 340 return nullptr;
329 } 341 }
330 342
331 Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) { 343 Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
344 std::lock_guard<GlobalLockType> L(GlobalLock);
332 ConstantInt1 &= INT8_C(1); 345 ConstantInt1 &= INT8_C(1);
333 return ConstPool->Integers1.getOrAdd(this, ConstantInt1); 346 return ConstPool->Integers1.getOrAdd(this, ConstantInt1);
334 } 347 }
335 348
336 Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) { 349 Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
350 std::lock_guard<GlobalLockType> L(GlobalLock);
337 return ConstPool->Integers8.getOrAdd(this, ConstantInt8); 351 return ConstPool->Integers8.getOrAdd(this, ConstantInt8);
338 } 352 }
339 353
340 Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) { 354 Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
355 std::lock_guard<GlobalLockType> L(GlobalLock);
341 return ConstPool->Integers16.getOrAdd(this, ConstantInt16); 356 return ConstPool->Integers16.getOrAdd(this, ConstantInt16);
342 } 357 }
343 358
344 Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) { 359 Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
360 std::lock_guard<GlobalLockType> L(GlobalLock);
345 return ConstPool->Integers32.getOrAdd(this, ConstantInt32); 361 return ConstPool->Integers32.getOrAdd(this, ConstantInt32);
346 } 362 }
347 363
348 Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) { 364 Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
365 std::lock_guard<GlobalLockType> L(GlobalLock);
349 return ConstPool->Integers64.getOrAdd(this, ConstantInt64); 366 return ConstPool->Integers64.getOrAdd(this, ConstantInt64);
350 } 367 }
351 368
352 Constant *GlobalContext::getConstantFloat(float ConstantFloat) { 369 Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
370 std::lock_guard<GlobalLockType> L(GlobalLock);
353 return ConstPool->Floats.getOrAdd(this, ConstantFloat); 371 return ConstPool->Floats.getOrAdd(this, ConstantFloat);
354 } 372 }
355 373
356 Constant *GlobalContext::getConstantDouble(double ConstantDouble) { 374 Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
375 std::lock_guard<GlobalLockType> L(GlobalLock);
357 return ConstPool->Doubles.getOrAdd(this, ConstantDouble); 376 return ConstPool->Doubles.getOrAdd(this, ConstantDouble);
358 } 377 }
359 378
360 Constant *GlobalContext::getConstantSym(RelocOffsetT Offset, 379 Constant *GlobalContext::getConstantSym(RelocOffsetT Offset,
361 const IceString &Name, 380 const IceString &Name,
362 bool SuppressMangling) { 381 bool SuppressMangling) {
382 std::lock_guard<GlobalLockType> L(GlobalLock);
363 return ConstPool->Relocatables.getOrAdd( 383 return ConstPool->Relocatables.getOrAdd(
364 this, RelocatableTuple(Offset, Name, SuppressMangling)); 384 this, RelocatableTuple(Offset, Name, SuppressMangling));
365 } 385 }
366 386
367 Constant *GlobalContext::getConstantUndef(Type Ty) { 387 Constant *GlobalContext::getConstantUndef(Type Ty) {
388 std::lock_guard<GlobalLockType> L(GlobalLock);
368 return ConstPool->Undefs.getOrAdd(this, Ty); 389 return ConstPool->Undefs.getOrAdd(this, Ty);
369 } 390 }
370 391
392 // All locking is done by the getConstant*() target function.
371 Constant *GlobalContext::getConstantZero(Type Ty) { 393 Constant *GlobalContext::getConstantZero(Type Ty) {
372 switch (Ty) { 394 switch (Ty) {
373 case IceType_i1: 395 case IceType_i1:
374 return getConstantInt1(0); 396 return getConstantInt1(0);
375 case IceType_i8: 397 case IceType_i8:
376 return getConstantInt8(0); 398 return getConstantInt8(0);
377 case IceType_i16: 399 case IceType_i16:
378 return getConstantInt16(0); 400 return getConstantInt16(0);
379 case IceType_i32: 401 case IceType_i32:
380 return getConstantInt32(0); 402 return getConstantInt32(0);
(...skipping 15 matching lines...)
396 BaseOS << "Unsupported constant type: " << Ty; 418 BaseOS << "Unsupported constant type: " << Ty;
397 llvm_unreachable(BaseOS.str().c_str()); 419 llvm_unreachable(BaseOS.str().c_str());
398 } break; 420 } break;
399 case IceType_void: 421 case IceType_void:
400 case IceType_NUM: 422 case IceType_NUM:
401 break; 423 break;
402 } 424 }
403 llvm_unreachable("Unknown type"); 425 llvm_unreachable("Unknown type");
404 } 426 }
405 427
406 ConstantList GlobalContext::getConstantPool(Type Ty) const { 428 ConstantList GlobalContext::getConstantPool(Type Ty) {
429 std::lock_guard<GlobalLockType> L(GlobalLock);
407 switch (Ty) { 430 switch (Ty) {
408 case IceType_i1: 431 case IceType_i1:
409 case IceType_i8: 432 case IceType_i8:
410 case IceType_i16: 433 case IceType_i16:
411 case IceType_i32: 434 case IceType_i32:
412 return ConstPool->Integers32.getConstantPool(); 435 return ConstPool->Integers32.getConstantPool();
413 case IceType_i64: 436 case IceType_i64:
414 return ConstPool->Integers64.getConstantPool(); 437 return ConstPool->Integers64.getConstantPool();
415 case IceType_f32: 438 case IceType_f32:
416 return ConstPool->Floats.getConstantPool(); 439 return ConstPool->Floats.getConstantPool();
(...skipping 11 matching lines...)
428 BaseOS << "Unsupported constant type: " << Ty; 451 BaseOS << "Unsupported constant type: " << Ty;
429 llvm_unreachable(BaseOS.str().c_str()); 452 llvm_unreachable(BaseOS.str().c_str());
430 } break; 453 } break;
431 case IceType_void: 454 case IceType_void:
432 case IceType_NUM: 455 case IceType_NUM:
433 break; 456 break;
434 } 457 }
435 llvm_unreachable("Unknown type"); 458 llvm_unreachable("Unknown type");
436 } 459 }
437 460
461 // No locking because only the bitcode parser thread calls it.
jvoung (off chromium) 2015/01/15 18:20:40 fwiw, chrome has a "base/threading/thread_checker.
Jim Stichnoth 2015/01/17 18:44:17 Acknowledged. Also, on further inspection, this m
438 FunctionDeclaration * 462 FunctionDeclaration *
439 GlobalContext::newFunctionDeclaration(const FuncSigType *Signature, 463 GlobalContext::newFunctionDeclaration(const FuncSigType *Signature,
440 unsigned CallingConv, unsigned Linkage, 464 unsigned CallingConv, unsigned Linkage,
441 bool IsProto) { 465 bool IsProto) {
442 FunctionDeclaration *Func = new FunctionDeclaration( 466 FunctionDeclaration *Func = new FunctionDeclaration(
443 *Signature, static_cast<llvm::CallingConv::ID>(CallingConv), 467 *Signature, static_cast<llvm::CallingConv::ID>(CallingConv),
444 static_cast<llvm::GlobalValue::LinkageTypes>(Linkage), IsProto); 468 static_cast<llvm::GlobalValue::LinkageTypes>(Linkage), IsProto);
445 GlobalDeclarations.push_back(Func); 469 GlobalDeclarations.push_back(Func);
446 return Func; 470 return Func;
447 } 471 }
448 472
473 // No locking because only the bitcode parser thread calls it.
449 VariableDeclaration *GlobalContext::newVariableDeclaration() { 474 VariableDeclaration *GlobalContext::newVariableDeclaration() {
450 VariableDeclaration *Var = new VariableDeclaration(); 475 VariableDeclaration *Var = new VariableDeclaration();
451 GlobalDeclarations.push_back(Var); 476 GlobalDeclarations.push_back(Var);
452 return Var; 477 return Var;
453 } 478 }
454 479
455 TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
456 const IceString &Name) {
457 assert(StackID < Timers.size());
458 return Timers[StackID].getTimerID(Name);
459 }
460
461 TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) { 480 TimerStackIdT GlobalContext::newTimerStackID(const IceString &Name) {
462 if (!ALLOW_DUMP) 481 if (!ALLOW_DUMP)
463 return 0; 482 return 0;
483 std::lock_guard<GlobalLockType> L(GlobalLock);
464 TimerStackIdT NewID = Timers.size(); 484 TimerStackIdT NewID = Timers.size();
465 Timers.push_back(TimerStack(Name)); 485 Timers.push_back(TimerStack(Name));
466 return NewID; 486 return NewID;
467 } 487 }
468 488
489 TimerIdT GlobalContext::getTimerID(TimerStackIdT StackID,
490 const IceString &Name) {
491 std::lock_guard<GlobalLockType> L(GlobalLock);
492 assert(StackID < Timers.size());
493 return Timers[StackID].getTimerID(Name);
494 }
495
469 void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) { 496 void GlobalContext::pushTimer(TimerIdT ID, TimerStackIdT StackID) {
497 std::lock_guard<GlobalLockType> L(GlobalLock);
470 assert(StackID < Timers.size()); 498 assert(StackID < Timers.size());
471 Timers[StackID].push(ID); 499 Timers[StackID].push(ID);
472 } 500 }
473 501
474 void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) { 502 void GlobalContext::popTimer(TimerIdT ID, TimerStackIdT StackID) {
503 std::lock_guard<GlobalLockType> L(GlobalLock);
475 assert(StackID < Timers.size()); 504 assert(StackID < Timers.size());
476 Timers[StackID].pop(ID); 505 Timers[StackID].pop(ID);
477 } 506 }
478 507
479 void GlobalContext::resetTimer(TimerStackIdT StackID) { 508 void GlobalContext::resetTimer(TimerStackIdT StackID) {
509 std::lock_guard<GlobalLockType> L(GlobalLock);
480 assert(StackID < Timers.size()); 510 assert(StackID < Timers.size());
481 Timers[StackID].reset(); 511 Timers[StackID].reset();
482 } 512 }
483 513
484 void GlobalContext::setTimerName(TimerStackIdT StackID, 514 void GlobalContext::setTimerName(TimerStackIdT StackID,
485 const IceString &NewName) { 515 const IceString &NewName) {
516 std::lock_guard<GlobalLockType> L(GlobalLock);
486 assert(StackID < Timers.size()); 517 assert(StackID < Timers.size());
487 Timers[StackID].setName(NewName); 518 Timers[StackID].setName(NewName);
488 } 519 }
489 520
490 void GlobalContext::dumpStats(const IceString &Name, bool Final) { 521 void GlobalContext::dumpStats(const IceString &Name, bool Final) {
491 if (!ALLOW_DUMP) 522 if (!ALLOW_DUMP || !getFlags().DumpStats)
492 return; 523 return;
493 if (Flags.DumpStats) { 524 std::lock_guard<GlobalLockType> L(GlobalLock);
494 if (Final) { 525 OstreamLocker OL(this);
495 StatsCumulative.dump(Name, getStrDump()); 526 if (Final) {
496 } else { 527 StatsCumulative.dump(Name, getStrDump());
497 StatsFunction.dump(Name, getStrDump()); 528 } else {
498 StatsCumulative.dump("_TOTAL_", getStrDump()); 529 TLS->StatsFunction.dump(Name, getStrDump());
499 } 530 StatsCumulative.dump("_TOTAL_", getStrDump());
500 } 531 }
501 } 532 }
502 533
503 void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) { 534 void GlobalContext::dumpTimers(TimerStackIdT StackID, bool DumpCumulative) {
504 if (!ALLOW_DUMP) 535 if (!ALLOW_DUMP)
505 return; 536 return;
506 assert(Timers.size() > StackID); 537 assert(Timers.size() > StackID);
538 OstreamLocker L(this);
507 Timers[StackID].dump(getStrDump(), DumpCumulative); 539 Timers[StackID].dump(getStrDump(), DumpCumulative);
508 } 540 }
509 541
510 TimerMarker::TimerMarker(TimerIdT ID, const Cfg *Func) 542 TimerMarker::TimerMarker(TimerIdT ID, const Cfg *Func)
511 : ID(ID), Ctx(Func->getContext()), Active(false) { 543 : ID(ID), Ctx(Func->getContext()), Active(false) {
512 if (ALLOW_DUMP) { 544 if (ALLOW_DUMP) {
513 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled; 545 Active = Func->getFocusedTiming() || Ctx->getFlags().SubzeroTimingEnabled;
514 if (Active) 546 if (Active)
515 Ctx->pushTimer(ID); 547 Ctx->pushTimer(ID);
516 } 548 }
517 } 549 }
518 550
551 thread_local GlobalContext::ThreadContext *GlobalContext::TLS;
552
519 } // end of namespace Ice 553 } // end of namespace Ice
OLDNEW

Powered by Google App Engine