From: yangguo@chromium.org Date: Tue, 29 Apr 2014 13:58:55 +0000 (+0000) Subject: Hide heap methods where possible. X-Git-Tag: upstream/4.7.83~9354 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=30e2802e12dd05aa46f1078c14d2919ff024687d;p=platform%2Fupstream%2Fv8.git Hide heap methods where possible. Factory is already a friend class of Heap. We introduce a TestHeap class in cctest.h to access protected methods. R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/247263003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21053 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/factory.cc b/src/factory.cc index 355e24f..e12d296 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -631,10 +631,9 @@ Handle Factory::NewSymbol() { Handle Factory::NewPrivateSymbol() { - CALL_HEAP_FUNCTION( - isolate(), - isolate()->heap()->AllocatePrivateSymbol(), - Symbol); + Handle symbol = NewSymbol(); + symbol->set_is_private(true); + return symbol; } @@ -1333,9 +1332,9 @@ Handle Factory::NewExternal(void* value) { } -Handle NewCodeHelper(Isolate* isolate, int object_size, bool immovable) { - CALL_HEAP_FUNCTION(isolate, - isolate->heap()->AllocateCode(object_size, immovable), +Handle Factory::NewCodeRaw(int object_size, bool immovable) { + CALL_HEAP_FUNCTION(isolate(), + isolate()->heap()->AllocateCode(object_size, immovable), Code); } @@ -1354,7 +1353,7 @@ Handle Factory::NewCode(const CodeDesc& desc, int body_size = RoundUp(desc.instr_size, kObjectAlignment); int obj_size = Code::SizeFor(body_size); - Handle code = NewCodeHelper(isolate(), obj_size, immovable); + Handle code = NewCodeRaw(obj_size, immovable); ASSERT(!isolate()->code_range()->exists() || isolate()->code_range()->contains(code->address())); diff --git a/src/factory.h b/src/factory.h index 7b9a9b3..d79a9c9 100644 --- a/src/factory.h +++ b/src/factory.h @@ -656,6 +656,9 @@ class Factory V8_FINAL { AllocationSpace space, Handle allocation_site); + // Creates a code object that is not yet fully initialized yet. + inline Handle NewCodeRaw(int object_size, bool immovable); + // Initializes a function with a shared part and prototype. // Note: this code was factored out of NewFunction such that other parts of // the VM could use it. Specifically, a function that creates instances of diff --git a/src/heap.cc b/src/heap.cc index 0c1cc57..af1759b 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -4336,15 +4336,6 @@ MaybeObject* Heap::AllocateSymbol() { } -MaybeObject* Heap::AllocatePrivateSymbol() { - MaybeObject* maybe = AllocateSymbol(); - Symbol* symbol; - if (!maybe->To(&symbol)) return maybe; - symbol->set_is_private(true); - return symbol; -} - - MaybeObject* Heap::AllocateStruct(InstanceType type) { Map* map; switch (type) { diff --git a/src/heap.h b/src/heap.h index cb50109..8fb16c5 100644 --- a/src/heap.h +++ b/src/heap.h @@ -682,18 +682,6 @@ class Heap { return old_data_space_->allocation_limit_address(); } - // Allocates and initializes a new JavaScript object based on a - // constructor. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // If allocation_site is non-null, then a memento is emitted after the object - // that points to the site. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateJSObject( - JSFunction* constructor, - PretenureFlag pretenure = NOT_TENURED, - AllocationSite* allocation_site = NULL); - // Returns a deep copy of the JavaScript object. // Properties and elements are copied too. // Returns failure if allocation failed. @@ -701,44 +689,6 @@ class Heap { MUST_USE_RESULT MaybeObject* CopyJSObject(JSObject* source, AllocationSite* site = NULL); - // Allocates and initializes a new JavaScript object based on a map. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Passing an allocation site means that a memento will be created that - // points to the site. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateJSObjectFromMap( - Map* map, - PretenureFlag pretenure = NOT_TENURED, - bool alloc_props = true, - AllocationSite* allocation_site = NULL); - - // Allocates a heap object based on the map. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this function does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* Allocate(Map* map, AllocationSpace space, - AllocationSite* allocation_site = NULL); - - // Allocates a JS Map in the heap. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this function does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateMap( - InstanceType instance_type, - int instance_size, - ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND); - - // Allocates a partial map for bootstrapping. - MUST_USE_RESULT MaybeObject* AllocatePartialMap(InstanceType instance_type, - int instance_size); - - // Allocate a block of memory in the given space (filled with a filler). - // Used as a fall-back for generated code when the space is full. - MUST_USE_RESULT MaybeObject* AllocateFillerObject(int size, - bool double_align, - AllocationSpace space); - // Clear the Instanceof cache (used when a prototype changes). inline void ClearInstanceofCache(); @@ -748,32 +698,6 @@ class Heap { // For use during bootup. void RepairFreeListsAfterBoot(); - // Allocates and fully initializes a String. There are two String - // encodings: ASCII and two byte. One should choose between the three string - // allocation functions based on the encoding of the string buffer used to - // initialized the string. - // - ...FromAscii initializes the string from a buffer that is ASCII - // encoded (it does not check that the buffer is ASCII encoded) and the - // result will be ASCII encoded. - // - ...FromUTF8 initializes the string from a buffer that is UTF-8 - // encoded. If the characters are all single-byte characters, the - // result will be ASCII encoded, otherwise it will converted to two - // byte. - // - ...FromTwoByte initializes the string from a buffer that is two-byte - // encoded. If the characters are all single-byte characters, the - // result will be converted to ASCII, otherwise it will be left as - // two-byte. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateStringFromUtf8Slow( - Vector str, - int non_ascii_start, - PretenureFlag pretenure = NOT_TENURED); - MUST_USE_RESULT MaybeObject* AllocateStringFromTwoByte( - Vector str, - PretenureFlag pretenure = NOT_TENURED); - // Allocates an internalized string in old space based on the character // stream. Returns Failure::RetryAfterGC(requested_bytes, space) if the // allocation failed. @@ -798,44 +722,6 @@ class Heap { MUST_USE_RESULT inline MaybeObject* AllocateInternalizedStringImpl( T t, int chars, uint32_t hash_field); - template - MUST_USE_RESULT MaybeObject* AllocateInternalizedStringImpl( - T t, int chars, uint32_t hash_field); - - // Allocate a byte array of the specified length - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateByteArray( - int length, - PretenureFlag pretenure = NOT_TENURED); - - // Allocates an external array of the specified length and type. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateExternalArray( - int length, - ExternalArrayType array_type, - void* external_pointer, - PretenureFlag pretenure); - - // Allocates a fixed typed array of the specified length and type. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateFixedTypedArray( - int length, - ExternalArrayType array_type, - PretenureFlag pretenure); - - // Allocate a symbol in old space. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateSymbol(); - MUST_USE_RESULT MaybeObject* AllocatePrivateSymbol(); - // Allocates a fixed array initialized with undefined values // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. @@ -859,10 +745,6 @@ class Heap { // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. MUST_USE_RESULT inline MaybeObject* CopyFixedArray(FixedArray* src); - // Make a copy of src and return it. Returns - // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. - MUST_USE_RESULT MaybeObject* CopyAndTenureFixedCOWArray(FixedArray* src); - // Make a copy of src, set the map, and return the copy. Returns // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. MUST_USE_RESULT MaybeObject* CopyFixedArrayWithMap(FixedArray* src, Map* map); @@ -872,42 +754,16 @@ class Heap { MUST_USE_RESULT inline MaybeObject* CopyFixedDoubleArray( FixedDoubleArray* src); - // Make a copy of src, set the map, and return the copy. Returns - // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. - MUST_USE_RESULT MaybeObject* CopyFixedDoubleArrayWithMap( - FixedDoubleArray* src, Map* map); - // Make a copy of src and return it. Returns // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. MUST_USE_RESULT inline MaybeObject* CopyConstantPoolArray( ConstantPoolArray* src); - // Make a copy of src, set the map, and return the copy. Returns - // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. - MUST_USE_RESULT MaybeObject* CopyConstantPoolArrayWithMap( - ConstantPoolArray* src, Map* map); - - MUST_USE_RESULT MaybeObject* AllocateConstantPoolArray( - int number_of_int64_entries, - int number_of_code_ptr_entries, - int number_of_heap_ptr_entries, - int number_of_int32_entries); - - // Allocates a fixed double array with uninitialized values. Returns - // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateUninitializedFixedDoubleArray( - int length, - PretenureFlag pretenure = NOT_TENURED); - // AllocateHashTable is identical to AllocateFixedArray except // that the resulting object has hash_table_map as map. MUST_USE_RESULT MaybeObject* AllocateHashTable( int length, PretenureFlag pretenure = NOT_TENURED); - // Allocates a new utility object in the old generation. - MUST_USE_RESULT MaybeObject* AllocateStruct(InstanceType type); - // Sloppy mode arguments object size. static const int kSloppyArgumentsObjectSize = JSObject::kHeaderSize + 2 * kPointerSize; @@ -919,17 +775,6 @@ class Heap { // callee is only valid in sloppy mode. static const int kArgumentsCalleeIndex = 1; - // Allocates an arguments object - optionally with an elements array. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateArgumentsObject( - Object* callee, int length); - - // Allocated a HeapNumber from value. - MUST_USE_RESULT MaybeObject* AllocateHeapNumber( - double value, PretenureFlag pretenure = NOT_TENURED); - // Converts an int into either a Smi or a HeapNumber object. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. @@ -937,13 +782,6 @@ class Heap { MUST_USE_RESULT inline MaybeObject* NumberFromUint32( uint32_t value, PretenureFlag pretenure = NOT_TENURED); - // Allocates a new foreign object. - // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation - // failed. - // Please note this does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* AllocateForeign( - Address address, PretenureFlag pretenure = NOT_TENURED); - // Finalizes an external string by deleting the associated external // data and clearing the resource pointer. inline void FinalizeExternalString(String* string); @@ -959,21 +797,6 @@ class Heap { // Maintain marking consistency for IncrementalMarking. void AdjustLiveBytes(Address address, int by, InvocationMode mode); - MUST_USE_RESULT MaybeObject* AllocateCode(int object_size, bool immovable); - - MUST_USE_RESULT MaybeObject* CopyCode(Code* code); - - // Copy the code and scope info part of the code object, but insert - // the provided data as the relocation information. - MUST_USE_RESULT MaybeObject* CopyCode(Code* code, Vector reloc_info); - - // Finds the internalized copy for string in the string table. - // If not found, a new string is added to the table and returned. - // Returns Failure::RetryAfterGC(requested_bytes, space) if allocation - // failed. - // Please note this function does not perform a garbage collection. - MUST_USE_RESULT MaybeObject* InternalizeStringWithKey(HashTableKey* key); - bool InternalizeStringIfExists(String* str, String** result); bool InternalizeTwoCharsStringIfExists(String* str, String** result); @@ -1673,6 +1496,52 @@ class Heap { static void FatalProcessOutOfMemory(const char* location, bool take_snapshot = false); + protected: + // Methods made available to tests. + + // Allocates a JS Map in the heap. + MUST_USE_RESULT MaybeObject* AllocateMap( + InstanceType instance_type, + int instance_size, + ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND); + + // Allocates and initializes a new JavaScript object based on a + // constructor. + // If allocation_site is non-null, then a memento is emitted after the object + // that points to the site. + MUST_USE_RESULT MaybeObject* AllocateJSObject( + JSFunction* constructor, + PretenureFlag pretenure = NOT_TENURED, + AllocationSite* allocation_site = NULL); + + // Allocates and initializes a new JavaScript object based on a map. + // Passing an allocation site means that a memento will be created that + // points to the site. + MUST_USE_RESULT MaybeObject* AllocateJSObjectFromMap( + Map* map, + PretenureFlag pretenure = NOT_TENURED, + bool alloc_props = true, + AllocationSite* allocation_site = NULL); + + // Allocated a HeapNumber from value. + MUST_USE_RESULT MaybeObject* AllocateHeapNumber( + double value, PretenureFlag pretenure = NOT_TENURED); + + // Allocate a byte array of the specified length + MUST_USE_RESULT MaybeObject* AllocateByteArray( + int length, + PretenureFlag pretenure = NOT_TENURED); + + // Allocates an arguments object - optionally with an elements array. + MUST_USE_RESULT MaybeObject* AllocateArgumentsObject( + Object* callee, int length); + + // Copy the code and scope info part of the code object, but insert + // the provided data as the relocation information. + MUST_USE_RESULT MaybeObject* CopyCode(Code* code, Vector reloc_info); + + MUST_USE_RESULT MaybeObject* CopyCode(Code* code); + private: Heap(); @@ -1929,6 +1798,27 @@ class Heap { AllocationSpace space, AllocationSpace retry_space); + // Allocates a heap object based on the map. + MUST_USE_RESULT MaybeObject* Allocate(Map* map, AllocationSpace space, + AllocationSite* allocation_site = NULL); + + // Allocates a partial map for bootstrapping. + MUST_USE_RESULT MaybeObject* AllocatePartialMap(InstanceType instance_type, + int instance_size); + + // Initializes a JSObject based on its map. + void InitializeJSObjectFromMap(JSObject* obj, + FixedArray* properties, + Map* map); + void InitializeAllocationMemento(AllocationMemento* memento, + AllocationSite* allocation_site); + + // Allocate a block of memory in the given space (filled with a filler). + // Used as a fall-back for generated code when the space is full. + MUST_USE_RESULT MaybeObject* AllocateFillerObject(int size, + bool double_align, + AllocationSpace space); + // Allocate an uninitialized fixed array. MUST_USE_RESULT MaybeObject* AllocateRawFixedArray( int length, PretenureFlag pretenure); @@ -1950,16 +1840,79 @@ class Heap { MUST_USE_RESULT MaybeObject* AllocateRawTwoByteString( int length, PretenureFlag pretenure); - // Initializes a JSObject based on its map. - void InitializeJSObjectFromMap(JSObject* obj, - FixedArray* properties, - Map* map); - void InitializeAllocationMemento(AllocationMemento* memento, - AllocationSite* allocation_site); + // Allocates and fully initializes a String. There are two String + // encodings: ASCII and two byte. One should choose between the three string + // allocation functions based on the encoding of the string buffer used to + // initialized the string. + // - ...FromAscii initializes the string from a buffer that is ASCII + // encoded (it does not check that the buffer is ASCII encoded) and the + // result will be ASCII encoded. + // - ...FromUTF8 initializes the string from a buffer that is UTF-8 + // encoded. If the characters are all single-byte characters, the + // result will be ASCII encoded, otherwise it will converted to two + // byte. + // - ...FromTwoByte initializes the string from a buffer that is two-byte + // encoded. If the characters are all single-byte characters, the + // result will be converted to ASCII, otherwise it will be left as + // two-byte. + MUST_USE_RESULT MaybeObject* AllocateStringFromUtf8Slow( + Vector str, + int non_ascii_start, + PretenureFlag pretenure = NOT_TENURED); + MUST_USE_RESULT MaybeObject* AllocateStringFromTwoByte( + Vector str, + PretenureFlag pretenure = NOT_TENURED); bool CreateInitialMaps(); void CreateInitialObjects(); + template + MUST_USE_RESULT MaybeObject* AllocateInternalizedStringImpl( + T t, int chars, uint32_t hash_field); + + // Computes a single character string where the character has code. + // A cache is used for ASCII codes. + MUST_USE_RESULT MaybeObject* LookupSingleCharacterStringFromCode( + uint16_t code); + + // Allocate a symbol in old space. + MUST_USE_RESULT MaybeObject* AllocateSymbol(); + + // Make a copy of src, set the map, and return the copy. + MUST_USE_RESULT MaybeObject* CopyConstantPoolArrayWithMap( + ConstantPoolArray* src, Map* map); + + MUST_USE_RESULT MaybeObject* AllocateConstantPoolArray( + int number_of_int64_entries, + int number_of_code_ptr_entries, + int number_of_heap_ptr_entries, + int number_of_int32_entries); + + // Allocates an external array of the specified length and type. + MUST_USE_RESULT MaybeObject* AllocateExternalArray( + int length, + ExternalArrayType array_type, + void* external_pointer, + PretenureFlag pretenure); + + // Allocates a fixed typed array of the specified length and type. + MUST_USE_RESULT MaybeObject* AllocateFixedTypedArray( + int length, + ExternalArrayType array_type, + PretenureFlag pretenure); + + // Make a copy of src and return it. + MUST_USE_RESULT MaybeObject* CopyAndTenureFixedCOWArray(FixedArray* src); + + // Make a copy of src, set the map, and return the copy. + MUST_USE_RESULT MaybeObject* CopyFixedDoubleArrayWithMap( + FixedDoubleArray* src, Map* map); + + // Allocates a fixed double array with uninitialized values. Returns + MUST_USE_RESULT MaybeObject* AllocateUninitializedFixedDoubleArray( + int length, + PretenureFlag pretenure = NOT_TENURED); + // These five Create*EntryStub functions are here and forced to not be inlined // because of a gcc-4.4 bug that assigns wrong vtable entries. NO_INLINE(void CreateJSEntryStub()); @@ -1987,6 +1940,19 @@ class Heap { // Allocate a tenured JS global property cell initialized with the hole. MUST_USE_RESULT MaybeObject* AllocatePropertyCell(); + // Allocates a new utility object in the old generation. + MUST_USE_RESULT MaybeObject* AllocateStruct(InstanceType type); + + // Allocates a new foreign object. + MUST_USE_RESULT MaybeObject* AllocateForeign( + Address address, PretenureFlag pretenure = NOT_TENURED); + + MUST_USE_RESULT MaybeObject* AllocateCode(int object_size, bool immovable); + + MUST_USE_RESULT MaybeObject* InternalizeStringWithKey(HashTableKey* key); + + MUST_USE_RESULT MaybeObject* InternalizeString(String* str); + // Performs a minor collection in new generation. void Scavenge(); diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h index b4e31f2..e0f3598 100644 --- a/test/cctest/cctest.h +++ b/test/cctest/cctest.h @@ -80,6 +80,19 @@ typedef v8::internal::EnumSet CcTestExtensionFlags; #undef DEFINE_EXTENSION_FLAG +// Use this to expose protected methods in i::Heap. +class TestHeap : public i::Heap { + public: + using i::Heap::AllocateHeapNumber; + using i::Heap::AllocateMap; + using i::Heap::AllocateJSObject; + using i::Heap::AllocateJSObjectFromMap; + using i::Heap::AllocateByteArray; + using i::Heap::AllocateArgumentsObject; + using i::Heap::CopyCode; +}; + + class CcTest { public: typedef void (TestFunction)(); @@ -107,6 +120,10 @@ class CcTest { return i_isolate()->heap(); } + static TestHeap* test_heap() { + return reinterpret_cast(i_isolate()->heap()); + } + static v8::Local global() { return isolate()->GetCurrentContext()->Global(); } diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc index 2aaa8dc..2ab6a92 100644 --- a/test/cctest/test-alloc.cc +++ b/test/cctest/test-alloc.cc @@ -38,7 +38,7 @@ using namespace v8::internal; static MaybeObject* AllocateAfterFailures() { static int attempts = 0; if (++attempts < 3) return Failure::RetryAfterGC(); - Heap* heap = CcTest::heap(); + TestHeap* heap = CcTest::test_heap(); // New space. SimulateFullSpace(heap->new_space()); diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 942d57e..342da9f 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -595,13 +595,20 @@ static const char* not_so_random_string_table[] = { static void CheckInternalizedStrings(const char** strings) { - Factory* factory = CcTest::i_isolate()->factory(); + Isolate* isolate = CcTest::i_isolate(); + Factory* factory = isolate->factory(); for (const char* string = *strings; *strings != 0; string = *strings++) { - Handle a = factory->InternalizeUtf8String(string); + HandleScope scope(isolate); + Handle a = + isolate->factory()->InternalizeUtf8String(CStrVector(string)); + // InternalizeUtf8String may return a failure if a GC is needed. CHECK(a->IsInternalizedString()); Handle b = factory->InternalizeUtf8String(string); CHECK_EQ(*b, *a); - CHECK(String::cast(*b)->IsUtf8EqualTo(CStrVector(string))); + CHECK(b->IsUtf8EqualTo(CStrVector(string))); + b = isolate->factory()->InternalizeUtf8String(CStrVector(string)); + CHECK_EQ(*b, *a); + CHECK(b->IsUtf8EqualTo(CStrVector(string))); } } @@ -977,7 +984,7 @@ TEST(Regression39128) { // Test case for crbug.com/39128. CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); - Heap* heap = isolate->heap(); + TestHeap* heap = CcTest::test_heap(); // Increase the chance of 'bump-the-pointer' allocation in old space. heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index 586b948..a685301 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -128,7 +128,7 @@ TEST(MarkCompactCollector) { FLAG_incremental_marking = false; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); - Heap* heap = isolate->heap(); + TestHeap* heap = CcTest::test_heap(); Factory* factory = isolate->factory(); v8::HandleScope sc(CcTest::isolate());