| Index: runtime/vm/scavenger.h | 
| diff --git a/runtime/vm/scavenger.h b/runtime/vm/scavenger.h | 
| index 82e9adc4badf3b5f1eb2aa1aac4a89cf24f4eaf0..1fd7c9fe2bd88b93e8f26e2c6b7964e11a0408bc 100644 | 
| --- a/runtime/vm/scavenger.h | 
| +++ b/runtime/vm/scavenger.h | 
| @@ -121,24 +121,46 @@ class Scavenger { | 
|  | 
| RawObject* FindObject(FindObjectVisitor* visitor) const; | 
|  | 
| -  uword TryAllocate(intptr_t size) { | 
| +  uword AllocateGC(intptr_t size) { | 
| ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 
| ASSERT(heap_ != Dart::vm_isolate()->heap()); | 
| +    ASSERT(scavenging_); | 
| +    uword result = top_; | 
| +    intptr_t remaining = end_ - top_; | 
| + | 
| +    // This allocation happens only in GC and only when copying objects to | 
| +    // the new to_ space. It must succeed. | 
| +    ASSERT(size <= remaining); | 
| +    ASSERT(to_->Contains(result)); | 
| +    ASSERT((result & kObjectAlignmentMask) == object_alignment_); | 
| +    top_ += size; | 
| +    ASSERT(to_->Contains(top_) || (top_ == to_->end())); | 
| +    return result; | 
| +  } | 
| + | 
| +  uword TryAllocateInTLAB(Thread* thread, intptr_t size) { | 
| +    ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 
| +    ASSERT(heap_ != Dart::vm_isolate()->heap()); | 
| +    ASSERT(thread->IsMutatorThread()); | 
| +    ASSERT(thread->isolate()->IsMutatorThreadScheduled()); | 
| #if defined(DEBUG) | 
| -    if (FLAG_gc_at_alloc && !scavenging_) { | 
| +    if (FLAG_gc_at_alloc) { | 
| +      ASSERT(!scavenging_); | 
| Scavenge(); | 
| } | 
| #endif | 
| -    uword result = top_; | 
| -    intptr_t remaining = end_ - top_; | 
| +    uword top = thread->top(); | 
| +    uword end = thread->end(); | 
| +    uword result = top; | 
| +    intptr_t remaining = end - top; | 
| if (remaining < size) { | 
| return 0; | 
| } | 
| ASSERT(to_->Contains(result)); | 
| ASSERT((result & kObjectAlignmentMask) == object_alignment_); | 
| - | 
| -    top_ += size; | 
| -    ASSERT(to_->Contains(top_) || (top_ == to_->end())); | 
| +    top += size; | 
| +    ASSERT(to_->Contains(top) || (top == to_->end())); | 
| +    thread->set_top(top); | 
| return result; | 
| } | 
|  | 
| @@ -149,11 +171,14 @@ class Scavenger { | 
| // Promote all live objects. | 
| void Evacuate(); | 
|  | 
| -  // Accessors to generate code for inlined allocation. | 
| -  uword* TopAddress() { return &top_; } | 
| -  uword* EndAddress() { return &end_; } | 
| -  static intptr_t top_offset() { return OFFSET_OF(Scavenger, top_); } | 
| -  static intptr_t end_offset() { return OFFSET_OF(Scavenger, end_); } | 
| +  uword top() { return top_; } | 
| +  uword end() { return end_; } | 
| + | 
| +  void set_top(uword value) { top_ = value; } | 
| +  void set_end(uword value) { | 
| +    ASSERT(to_->end() == value); | 
| +    end_ = value; | 
| +  } | 
|  | 
| int64_t UsedInWords() const { | 
| return (top_ - FirstObjectStart()) >> kWordSizeLog2; | 
| @@ -190,6 +215,8 @@ class Scavenger { | 
| void AllocateExternal(intptr_t size); | 
| void FreeExternal(intptr_t size); | 
|  | 
| +  void FlushTLS() const; | 
| + | 
| private: | 
| // Ids for time and data records in Heap::GCStats. | 
| enum { | 
| @@ -252,12 +279,6 @@ class Scavenger { | 
|  | 
| intptr_t NewSizeInWords(intptr_t old_size_in_words) const; | 
|  | 
| -  // Accessed from generated code. | 
| -  // ** This block of fields must come first! ** | 
| -  // For AOT cross-compilation, we rely on these members having the same offsets | 
| -  // in SIMARM(IA32) and ARM, and the same offsets in SIMARM64(X64) and ARM64. | 
| -  // We use only word-sized fields to avoid differences in struct packing on the | 
| -  // different architectures. See also CheckOffsets in dart.cc. | 
| uword top_; | 
| uword end_; | 
|  | 
|  |