OLD | NEW |
1 // Copyright 2006-2010 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #ifndef V8_HEAP_INL_H_ | 28 #ifndef V8_HEAP_INL_H_ |
29 #define V8_HEAP_INL_H_ | 29 #define V8_HEAP_INL_H_ |
30 | 30 |
31 #include "heap.h" | 31 #include "heap.h" |
32 #include "objects.h" | 32 #include "objects.h" |
| 33 #include "isolate.h" |
33 #include "v8-counters.h" | 34 #include "v8-counters.h" |
34 | 35 |
35 namespace v8 { | 36 namespace v8 { |
36 namespace internal { | 37 namespace internal { |
37 | 38 |
| 39 void PromotionQueue::insert(HeapObject* target, int size) { |
| 40 *(--rear_) = reinterpret_cast<intptr_t>(target); |
| 41 *(--rear_) = size; |
| 42 // Assert no overflow into live objects. |
| 43 ASSERT(reinterpret_cast<Address>(rear_) >= HEAP->new_space()->top()); |
| 44 } |
| 45 |
| 46 |
38 int Heap::MaxObjectSizeInPagedSpace() { | 47 int Heap::MaxObjectSizeInPagedSpace() { |
39 return Page::kMaxHeapObjectSize; | 48 return Page::kMaxHeapObjectSize; |
40 } | 49 } |
41 | 50 |
42 | 51 |
43 MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> str, | 52 MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> str, |
44 PretenureFlag pretenure) { | 53 PretenureFlag pretenure) { |
45 // Check for ASCII first since this is the common case. | 54 // Check for ASCII first since this is the common case. |
46 if (String::IsAscii(str.start(), str.length())) { | 55 if (String::IsAscii(str.start(), str.length())) { |
47 // If the string is ASCII, we do not need to convert the characters | 56 // If the string is ASCII, we do not need to convert the characters |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 ASSERT(space != NEW_SPACE || | 148 ASSERT(space != NEW_SPACE || |
140 retry_space == OLD_POINTER_SPACE || | 149 retry_space == OLD_POINTER_SPACE || |
141 retry_space == OLD_DATA_SPACE || | 150 retry_space == OLD_DATA_SPACE || |
142 retry_space == LO_SPACE); | 151 retry_space == LO_SPACE); |
143 #ifdef DEBUG | 152 #ifdef DEBUG |
144 if (FLAG_gc_interval >= 0 && | 153 if (FLAG_gc_interval >= 0 && |
145 !disallow_allocation_failure_ && | 154 !disallow_allocation_failure_ && |
146 Heap::allocation_timeout_-- <= 0) { | 155 Heap::allocation_timeout_-- <= 0) { |
147 return Failure::RetryAfterGC(space); | 156 return Failure::RetryAfterGC(space); |
148 } | 157 } |
149 Counters::objs_since_last_full.Increment(); | 158 isolate_->counters()->objs_since_last_full()->Increment(); |
150 Counters::objs_since_last_young.Increment(); | 159 isolate_->counters()->objs_since_last_young()->Increment(); |
151 #endif | 160 #endif |
152 MaybeObject* result; | 161 MaybeObject* result; |
153 if (NEW_SPACE == space) { | 162 if (NEW_SPACE == space) { |
154 result = new_space_.AllocateRaw(size_in_bytes); | 163 result = new_space_.AllocateRaw(size_in_bytes); |
155 if (always_allocate() && result->IsFailure()) { | 164 if (always_allocate() && result->IsFailure()) { |
156 space = retry_space; | 165 space = retry_space; |
157 } else { | 166 } else { |
158 return result; | 167 return result; |
159 } | 168 } |
160 } | 169 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 (*resource_addr)->Dispose(); | 216 (*resource_addr)->Dispose(); |
208 } | 217 } |
209 | 218 |
210 // Clear the resource pointer in the string. | 219 // Clear the resource pointer in the string. |
211 *resource_addr = NULL; | 220 *resource_addr = NULL; |
212 } | 221 } |
213 | 222 |
214 | 223 |
215 MaybeObject* Heap::AllocateRawMap() { | 224 MaybeObject* Heap::AllocateRawMap() { |
216 #ifdef DEBUG | 225 #ifdef DEBUG |
217 Counters::objs_since_last_full.Increment(); | 226 isolate_->counters()->objs_since_last_full()->Increment(); |
218 Counters::objs_since_last_young.Increment(); | 227 isolate_->counters()->objs_since_last_young()->Increment(); |
219 #endif | 228 #endif |
220 MaybeObject* result = map_space_->AllocateRaw(Map::kSize); | 229 MaybeObject* result = map_space_->AllocateRaw(Map::kSize); |
221 if (result->IsFailure()) old_gen_exhausted_ = true; | 230 if (result->IsFailure()) old_gen_exhausted_ = true; |
222 #ifdef DEBUG | 231 #ifdef DEBUG |
223 if (!result->IsFailure()) { | 232 if (!result->IsFailure()) { |
224 // Maps have their own alignment. | 233 // Maps have their own alignment. |
225 CHECK((reinterpret_cast<intptr_t>(result) & kMapAlignmentMask) == | 234 CHECK((reinterpret_cast<intptr_t>(result) & kMapAlignmentMask) == |
226 static_cast<intptr_t>(kHeapObjectTag)); | 235 static_cast<intptr_t>(kHeapObjectTag)); |
227 } | 236 } |
228 #endif | 237 #endif |
229 return result; | 238 return result; |
230 } | 239 } |
231 | 240 |
232 | 241 |
233 MaybeObject* Heap::AllocateRawCell() { | 242 MaybeObject* Heap::AllocateRawCell() { |
234 #ifdef DEBUG | 243 #ifdef DEBUG |
235 Counters::objs_since_last_full.Increment(); | 244 isolate_->counters()->objs_since_last_full()->Increment(); |
236 Counters::objs_since_last_young.Increment(); | 245 isolate_->counters()->objs_since_last_young()->Increment(); |
237 #endif | 246 #endif |
238 MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize); | 247 MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize); |
239 if (result->IsFailure()) old_gen_exhausted_ = true; | 248 if (result->IsFailure()) old_gen_exhausted_ = true; |
240 return result; | 249 return result; |
241 } | 250 } |
242 | 251 |
243 | 252 |
244 bool Heap::InNewSpace(Object* object) { | 253 bool Heap::InNewSpace(Object* object) { |
245 bool result = new_space_.Contains(object); | 254 bool result = new_space_.Contains(object); |
246 ASSERT(!result || // Either not in new space | 255 ASSERT(!result || // Either not in new space |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 ASSERT(IsAligned(byte_size, kPointerSize)); | 343 ASSERT(IsAligned(byte_size, kPointerSize)); |
335 | 344 |
336 Page* page = Page::FromAddress(dst); | 345 Page* page = Page::FromAddress(dst); |
337 uint32_t marks = page->GetRegionMarks(); | 346 uint32_t marks = page->GetRegionMarks(); |
338 | 347 |
339 for (int remaining = byte_size / kPointerSize; | 348 for (int remaining = byte_size / kPointerSize; |
340 remaining > 0; | 349 remaining > 0; |
341 remaining--) { | 350 remaining--) { |
342 Memory::Object_at(dst) = Memory::Object_at(src); | 351 Memory::Object_at(dst) = Memory::Object_at(src); |
343 | 352 |
344 if (Heap::InNewSpace(Memory::Object_at(dst))) { | 353 if (InNewSpace(Memory::Object_at(dst))) { |
345 marks |= page->GetRegionMaskForAddress(dst); | 354 marks |= page->GetRegionMaskForAddress(dst); |
346 } | 355 } |
347 | 356 |
348 dst += kPointerSize; | 357 dst += kPointerSize; |
349 src += kPointerSize; | 358 src += kPointerSize; |
350 } | 359 } |
351 | 360 |
352 page->SetRegionMarks(marks); | 361 page->SetRegionMarks(marks); |
353 } | 362 } |
354 | 363 |
(...skipping 25 matching lines...) Expand all Loading... |
380 Address src, | 389 Address src, |
381 int byte_size) { | 390 int byte_size) { |
382 ASSERT(IsAligned(byte_size, kPointerSize)); | 391 ASSERT(IsAligned(byte_size, kPointerSize)); |
383 ASSERT((dst >= (src + byte_size)) || | 392 ASSERT((dst >= (src + byte_size)) || |
384 ((OffsetFrom(src) - OffsetFrom(dst)) >= kPointerSize)); | 393 ((OffsetFrom(src) - OffsetFrom(dst)) >= kPointerSize)); |
385 | 394 |
386 CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, byte_size); | 395 CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, byte_size); |
387 } | 396 } |
388 | 397 |
389 | 398 |
| 399 void Heap::ScavengePointer(HeapObject** p) { |
| 400 ScavengeObject(p, *p); |
| 401 } |
| 402 |
| 403 |
390 void Heap::ScavengeObject(HeapObject** p, HeapObject* object) { | 404 void Heap::ScavengeObject(HeapObject** p, HeapObject* object) { |
391 ASSERT(InFromSpace(object)); | 405 ASSERT(HEAP->InFromSpace(object)); |
392 | 406 |
393 // We use the first word (where the map pointer usually is) of a heap | 407 // We use the first word (where the map pointer usually is) of a heap |
394 // object to record the forwarding pointer. A forwarding pointer can | 408 // object to record the forwarding pointer. A forwarding pointer can |
395 // point to an old space, the code space, or the to space of the new | 409 // point to an old space, the code space, or the to space of the new |
396 // generation. | 410 // generation. |
397 MapWord first_word = object->map_word(); | 411 MapWord first_word = object->map_word(); |
398 | 412 |
399 // If the first word is a forwarding address, the object has already been | 413 // If the first word is a forwarding address, the object has already been |
400 // copied. | 414 // copied. |
401 if (first_word.IsForwardingAddress()) { | 415 if (first_word.IsForwardingAddress()) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 } | 468 } |
455 ASSERT(amount_of_external_allocated_memory_ >= 0); | 469 ASSERT(amount_of_external_allocated_memory_ >= 0); |
456 return amount_of_external_allocated_memory_; | 470 return amount_of_external_allocated_memory_; |
457 } | 471 } |
458 | 472 |
459 | 473 |
460 void Heap::SetLastScriptId(Object* last_script_id) { | 474 void Heap::SetLastScriptId(Object* last_script_id) { |
461 roots_[kLastScriptIdRootIndex] = last_script_id; | 475 roots_[kLastScriptIdRootIndex] = last_script_id; |
462 } | 476 } |
463 | 477 |
| 478 Isolate* Heap::isolate() { |
| 479 return reinterpret_cast<Isolate*>(reinterpret_cast<intptr_t>(this) - |
| 480 reinterpret_cast<size_t>(reinterpret_cast<Isolate*>(4)->heap()) + 4); |
| 481 } |
| 482 |
464 | 483 |
465 #ifdef DEBUG | 484 #ifdef DEBUG |
466 #define GC_GREEDY_CHECK() \ | 485 #define GC_GREEDY_CHECK() \ |
467 if (FLAG_gc_greedy) v8::internal::Heap::GarbageCollectionGreedyCheck() | 486 if (FLAG_gc_greedy) HEAP->GarbageCollectionGreedyCheck() |
468 #else | 487 #else |
469 #define GC_GREEDY_CHECK() { } | 488 #define GC_GREEDY_CHECK() { } |
470 #endif | 489 #endif |
471 | 490 |
472 | 491 |
473 // Calls the FUNCTION_CALL function and retries it up to three times | 492 // Calls the FUNCTION_CALL function and retries it up to three times |
474 // to guarantee that any allocations performed during the call will | 493 // to guarantee that any allocations performed during the call will |
475 // succeed if there's enough memory. | 494 // succeed if there's enough memory. |
476 | 495 |
477 // Warning: Do not use the identifiers __object__, __maybe_object__ or | 496 // Warning: Do not use the identifiers __object__, __maybe_object__ or |
478 // __scope__ in a call to this macro. | 497 // __scope__ in a call to this macro. |
479 | 498 |
480 #define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY) \ | 499 #define CALL_AND_RETRY(ISOLATE, FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY)\ |
481 do { \ | 500 do { \ |
482 GC_GREEDY_CHECK(); \ | 501 GC_GREEDY_CHECK(); \ |
483 MaybeObject* __maybe_object__ = FUNCTION_CALL; \ | 502 MaybeObject* __maybe_object__ = FUNCTION_CALL; \ |
484 Object* __object__ = NULL; \ | 503 Object* __object__ = NULL; \ |
485 if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ | 504 if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ |
486 if (__maybe_object__->IsOutOfMemory()) { \ | 505 if (__maybe_object__->IsOutOfMemory()) { \ |
487 v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\ | 506 v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\ |
488 } \ | 507 } \ |
489 if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \ | 508 if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \ |
490 Heap::CollectGarbage( \ | 509 ISOLATE->heap()->CollectGarbage(Failure::cast(__maybe_object__)-> \ |
491 Failure::cast(__maybe_object__)->allocation_space()); \ | 510 allocation_space()); \ |
492 __maybe_object__ = FUNCTION_CALL; \ | 511 __maybe_object__ = FUNCTION_CALL; \ |
493 if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ | 512 if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ |
494 if (__maybe_object__->IsOutOfMemory()) { \ | 513 if (__maybe_object__->IsOutOfMemory()) { \ |
495 v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\ | 514 v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\ |
496 } \ | 515 } \ |
497 if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \ | 516 if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \ |
498 Counters::gc_last_resort_from_handles.Increment(); \ | 517 ISOLATE->counters()->gc_last_resort_from_handles()->Increment(); \ |
499 Heap::CollectAllAvailableGarbage(); \ | 518 ISOLATE->heap()->CollectAllAvailableGarbage(); \ |
500 { \ | 519 { \ |
501 AlwaysAllocateScope __scope__; \ | 520 AlwaysAllocateScope __scope__; \ |
502 __maybe_object__ = FUNCTION_CALL; \ | 521 __maybe_object__ = FUNCTION_CALL; \ |
503 } \ | 522 } \ |
504 if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ | 523 if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ |
505 if (__maybe_object__->IsOutOfMemory() || \ | 524 if (__maybe_object__->IsOutOfMemory() || \ |
506 __maybe_object__->IsRetryAfterGC()) { \ | 525 __maybe_object__->IsRetryAfterGC()) { \ |
507 /* TODO(1181417): Fix this. */ \ | 526 /* TODO(1181417): Fix this. */ \ |
508 v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\ | 527 v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\ |
509 } \ | 528 } \ |
510 RETURN_EMPTY; \ | 529 RETURN_EMPTY; \ |
511 } while (false) | 530 } while (false) |
512 | 531 |
513 | 532 |
514 #define CALL_HEAP_FUNCTION(FUNCTION_CALL, TYPE) \ | 533 // TODO(isolates): cache isolate: either accept as a parameter or |
515 CALL_AND_RETRY(FUNCTION_CALL, \ | 534 // set to some known symbol (__CUR_ISOLATE__?) |
516 return Handle<TYPE>(TYPE::cast(__object__)), \ | 535 #define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE) \ |
| 536 CALL_AND_RETRY(ISOLATE, \ |
| 537 FUNCTION_CALL, \ |
| 538 return Handle<TYPE>(TYPE::cast(__object__), ISOLATE), \ |
517 return Handle<TYPE>()) | 539 return Handle<TYPE>()) |
518 | 540 |
519 | 541 |
520 #define CALL_HEAP_FUNCTION_VOID(FUNCTION_CALL) \ | 542 #define CALL_HEAP_FUNCTION_VOID(ISOLATE, FUNCTION_CALL) \ |
521 CALL_AND_RETRY(FUNCTION_CALL, return, return) | 543 CALL_AND_RETRY(ISOLATE, FUNCTION_CALL, return, return) |
522 | 544 |
523 | 545 |
524 #ifdef DEBUG | 546 #ifdef DEBUG |
525 | 547 |
526 inline bool Heap::allow_allocation(bool new_state) { | 548 inline bool Heap::allow_allocation(bool new_state) { |
527 bool old = allocation_allowed_; | 549 bool old = allocation_allowed_; |
528 allocation_allowed_ = new_state; | 550 allocation_allowed_ = new_state; |
529 return old; | 551 return old; |
530 } | 552 } |
531 | 553 |
532 #endif | 554 #endif |
533 | 555 |
534 | 556 |
535 void ExternalStringTable::AddString(String* string) { | 557 void ExternalStringTable::AddString(String* string) { |
536 ASSERT(string->IsExternalString()); | 558 ASSERT(string->IsExternalString()); |
537 if (Heap::InNewSpace(string)) { | 559 if (heap_->InNewSpace(string)) { |
538 new_space_strings_.Add(string); | 560 new_space_strings_.Add(string); |
539 } else { | 561 } else { |
540 old_space_strings_.Add(string); | 562 old_space_strings_.Add(string); |
541 } | 563 } |
542 } | 564 } |
543 | 565 |
544 | 566 |
545 void ExternalStringTable::Iterate(ObjectVisitor* v) { | 567 void ExternalStringTable::Iterate(ObjectVisitor* v) { |
546 if (!new_space_strings_.is_empty()) { | 568 if (!new_space_strings_.is_empty()) { |
547 Object** start = &new_space_strings_[0]; | 569 Object** start = &new_space_strings_[0]; |
548 v->VisitPointers(start, start + new_space_strings_.length()); | 570 v->VisitPointers(start, start + new_space_strings_.length()); |
549 } | 571 } |
550 if (!old_space_strings_.is_empty()) { | 572 if (!old_space_strings_.is_empty()) { |
551 Object** start = &old_space_strings_[0]; | 573 Object** start = &old_space_strings_[0]; |
552 v->VisitPointers(start, start + old_space_strings_.length()); | 574 v->VisitPointers(start, start + old_space_strings_.length()); |
553 } | 575 } |
554 } | 576 } |
555 | 577 |
556 | 578 |
557 // Verify() is inline to avoid ifdef-s around its calls in release | 579 // Verify() is inline to avoid ifdef-s around its calls in release |
558 // mode. | 580 // mode. |
559 void ExternalStringTable::Verify() { | 581 void ExternalStringTable::Verify() { |
560 #ifdef DEBUG | 582 #ifdef DEBUG |
561 for (int i = 0; i < new_space_strings_.length(); ++i) { | 583 for (int i = 0; i < new_space_strings_.length(); ++i) { |
562 ASSERT(Heap::InNewSpace(new_space_strings_[i])); | 584 ASSERT(heap_->InNewSpace(new_space_strings_[i])); |
563 ASSERT(new_space_strings_[i] != Heap::raw_unchecked_null_value()); | 585 ASSERT(new_space_strings_[i] != HEAP->raw_unchecked_null_value()); |
564 } | 586 } |
565 for (int i = 0; i < old_space_strings_.length(); ++i) { | 587 for (int i = 0; i < old_space_strings_.length(); ++i) { |
566 ASSERT(!Heap::InNewSpace(old_space_strings_[i])); | 588 ASSERT(!heap_->InNewSpace(old_space_strings_[i])); |
567 ASSERT(old_space_strings_[i] != Heap::raw_unchecked_null_value()); | 589 ASSERT(old_space_strings_[i] != HEAP->raw_unchecked_null_value()); |
568 } | 590 } |
569 #endif | 591 #endif |
570 } | 592 } |
571 | 593 |
572 | 594 |
573 void ExternalStringTable::AddOldString(String* string) { | 595 void ExternalStringTable::AddOldString(String* string) { |
574 ASSERT(string->IsExternalString()); | 596 ASSERT(string->IsExternalString()); |
575 ASSERT(!Heap::InNewSpace(string)); | 597 ASSERT(!heap_->InNewSpace(string)); |
576 old_space_strings_.Add(string); | 598 old_space_strings_.Add(string); |
577 } | 599 } |
578 | 600 |
579 | 601 |
580 void ExternalStringTable::ShrinkNewStrings(int position) { | 602 void ExternalStringTable::ShrinkNewStrings(int position) { |
581 new_space_strings_.Rewind(position); | 603 new_space_strings_.Rewind(position); |
582 Verify(); | 604 Verify(); |
583 } | 605 } |
584 | 606 |
| 607 |
| 608 void Heap::ClearInstanceofCache() { |
| 609 set_instanceof_cache_function(the_hole_value()); |
| 610 } |
| 611 |
| 612 |
| 613 Object* Heap::ToBoolean(bool condition) { |
| 614 return condition ? true_value() : false_value(); |
| 615 } |
| 616 |
| 617 |
| 618 void Heap::CompletelyClearInstanceofCache() { |
| 619 set_instanceof_cache_map(the_hole_value()); |
| 620 set_instanceof_cache_function(the_hole_value()); |
| 621 } |
| 622 |
| 623 |
| 624 MaybeObject* TranscendentalCache::Get(Type type, double input) { |
| 625 SubCache* cache = caches_[type]; |
| 626 if (cache == NULL) { |
| 627 caches_[type] = cache = new SubCache(type); |
| 628 } |
| 629 return cache->Get(input); |
| 630 } |
| 631 |
| 632 |
| 633 Address TranscendentalCache::cache_array_address() { |
| 634 return reinterpret_cast<Address>(caches_); |
| 635 } |
| 636 |
| 637 |
| 638 double TranscendentalCache::SubCache::Calculate(double input) { |
| 639 switch (type_) { |
| 640 case ACOS: |
| 641 return acos(input); |
| 642 case ASIN: |
| 643 return asin(input); |
| 644 case ATAN: |
| 645 return atan(input); |
| 646 case COS: |
| 647 return cos(input); |
| 648 case EXP: |
| 649 return exp(input); |
| 650 case LOG: |
| 651 return log(input); |
| 652 case SIN: |
| 653 return sin(input); |
| 654 case TAN: |
| 655 return tan(input); |
| 656 default: |
| 657 return 0.0; // Never happens. |
| 658 } |
| 659 } |
| 660 |
| 661 |
| 662 MaybeObject* TranscendentalCache::SubCache::Get(double input) { |
| 663 Converter c; |
| 664 c.dbl = input; |
| 665 int hash = Hash(c); |
| 666 Element e = elements_[hash]; |
| 667 if (e.in[0] == c.integers[0] && |
| 668 e.in[1] == c.integers[1]) { |
| 669 ASSERT(e.output != NULL); |
| 670 isolate_->counters()->transcendental_cache_hit()->Increment(); |
| 671 return e.output; |
| 672 } |
| 673 double answer = Calculate(input); |
| 674 isolate_->counters()->transcendental_cache_miss()->Increment(); |
| 675 Object* heap_number; |
| 676 { MaybeObject* maybe_heap_number = |
| 677 isolate_->heap()->AllocateHeapNumber(answer); |
| 678 if (!maybe_heap_number->ToObject(&heap_number)) return maybe_heap_number; |
| 679 } |
| 680 elements_[hash].in[0] = c.integers[0]; |
| 681 elements_[hash].in[1] = c.integers[1]; |
| 682 elements_[hash].output = heap_number; |
| 683 return heap_number; |
| 684 } |
| 685 |
| 686 |
| 687 Heap* _inline_get_heap_() { |
| 688 return HEAP; |
| 689 } |
| 690 |
| 691 |
| 692 void MarkCompactCollector::SetMark(HeapObject* obj) { |
| 693 tracer_->increment_marked_count(); |
| 694 #ifdef DEBUG |
| 695 UpdateLiveObjectCount(obj); |
| 696 #endif |
| 697 obj->SetMark(); |
| 698 } |
| 699 |
| 700 |
585 } } // namespace v8::internal | 701 } } // namespace v8::internal |
586 | 702 |
587 #endif // V8_HEAP_INL_H_ | 703 #endif // V8_HEAP_INL_H_ |
OLD | NEW |