typedef void (*GCCallback)();
-// --- E x t e r n a l S y m b o l C a l l b a c k ---
-
-/**
- * Callback used to allocate certain V8 symbols as external strings.
- *
- * The data passed to the callback is utf8 encoded.
- *
- * Allocations are not allowed in the callback function, you therefore
- * cannot manipulate objects (set or delete properties for example)
- * since it is possible such operations will result in the allocation
- * of objects.
- */
-typedef String::ExternalStringResource* (*ExternalSymbolCallback)(
- const char* utf8,
- size_t length);
-
-
// --- C o n t e x t G e n e r a t o r ---
/**
static void SetGlobalGCEpilogueCallback(GCCallback);
/**
- * Applications can register a callback that will be used when
- * allocating most of the V8 symbols. The callback must return an
- * external string resource that represents the symbols.
- *
- * Most often when performing a property lookup the key will be a
- * symbol. Allocating symbols as external strings can reduce the
- * amount of string conversions needed when using interceptors and
- * accessors.
- *
- * \note This is an experimental feature and it might be removed.
- */
- static void SetExternalSymbolCallback(ExternalSymbolCallback);
-
- /**
* Allows the host application to group objects together. If one
* object in the group is alive, all objects in the group are alive.
* After each garbage collection, object groups are removed. It is
}
-void V8::SetExternalSymbolCallback(ExternalSymbolCallback callback) {
- if (IsDeadCheck("v8::V8::SetExternalSymbolCallback()")) return;
- i::Heap::SetExternalSymbolCallback(callback);
-}
-
void V8::PauseProfiler() {
#ifdef ENABLE_LOGGING_AND_PROFILING
i::Logger::PauseProfiler();
Object* Heap::AllocateSymbol(Vector<const char> str,
int chars,
uint32_t length_field) {
- if (global_external_symbol_callback_) {
- return AllocateExternalSymbol(str, chars);
- }
unibrow::Utf8InputBuffer<> buffer(str.start(),
static_cast<unsigned>(str.length()));
return AllocateInternalSymbol(&buffer, chars, length_field);
GCCallback Heap::global_gc_prologue_callback_ = NULL;
GCCallback Heap::global_gc_epilogue_callback_ = NULL;
-ExternalSymbolCallback Heap::global_external_symbol_callback_ = NULL;
-
// Variables set based on semispace_size_ and old_generation_size_ in
// ConfigureHeap.
int Heap::young_generation_size_ = 0; // Will be 2 * semispace_size_.
}
-Object* Heap::AllocateExternalSymbolFromTwoByte(
- ExternalTwoByteString::Resource* resource) {
- int length = resource->length();
-
- Map* map = ExternalTwoByteString::SymbolMap(length);
- Object* result = Allocate(map, OLD_DATA_SPACE);
- if (result->IsFailure()) return result;
-
- ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result);
- external_string->set_length(length);
- external_string->set_resource(resource);
-
- return result;
-}
-
-
Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
if (code <= String::kMaxAsciiCharCode) {
Object* value = Heap::single_character_string_cache()->get(code);
ASSERT(static_cast<unsigned>(chars) == buffer->Length());
// Determine whether the string is ascii.
bool is_ascii = true;
- while (buffer->has_more()) {
+ while (buffer->has_more() && is_ascii) {
if (buffer->GetNext() > unibrow::Utf8::kMaxOneByteChar) is_ascii = false;
}
buffer->Rewind();
}
-// External string resource that only contains a length field. These
-// are used temporarily when allocating external symbols.
-class DummyExternalStringResource
- : public v8::String::ExternalStringResource {
- public:
- explicit DummyExternalStringResource(size_t length) : length_(length) { }
-
- virtual const uint16_t* data() const {
- UNREACHABLE();
- return NULL;
- }
-
- virtual size_t length() const { return length_; }
- private:
- size_t length_;
-};
-
-
-Object* Heap::AllocateExternalSymbol(Vector<const char> string, int chars) {
- // Attempt to allocate the resulting external string first. Use a
- // dummy string resource that has the correct length so that we only
- // have to patch the external string resource after the callback.
- DummyExternalStringResource dummy_resource(chars);
- Object* obj = AllocateExternalSymbolFromTwoByte(&dummy_resource);
- if (obj->IsFailure()) return obj;
- // Perform callback.
- v8::String::ExternalStringResource* resource =
- global_external_symbol_callback_(string.start(), string.length());
- // Patch the resource pointer of the result.
- ExternalTwoByteString* result = ExternalTwoByteString::cast(obj);
- result->set_resource(resource);
- // Force hash code to be computed.
- result->Hash();
- ASSERT(result->IsEqualTo(string));
- return result;
-}
-
-
Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
int size = SeqAsciiString::SizeFor(length);
ExternalAsciiString::Resource* resource);
static Object* AllocateExternalStringFromTwoByte(
ExternalTwoByteString::Resource* resource);
- static Object* AllocateExternalSymbolFromTwoByte(
- ExternalTwoByteString::Resource* resource);
// Allocates an uninitialized object. The memory is non-executable if the
// hardware and OS allow.
global_gc_epilogue_callback_ = callback;
}
- static void SetExternalSymbolCallback(ExternalSymbolCallback callback) {
- global_external_symbol_callback_ = callback;
- }
-
// Heap roots
#define ROOT_ACCESSOR(type, name) static type* name() { return name##_; }
ROOT_LIST(ROOT_ACCESSOR)
static GCCallback global_gc_prologue_callback_;
static GCCallback global_gc_epilogue_callback_;
- // Callback function used for allocating external symbols.
- static ExternalSymbolCallback global_external_symbol_callback_;
-
// Checks whether a global GC is necessary
static GarbageCollector SelectGarbageCollector(AllocationSpace space);
}
-static String::ExternalStringResource* SymbolCallback(const char* chars,
- size_t length) {
- uint16_t* buffer = i::NewArray<uint16_t>(length + 1);
- for (size_t i = 0; i < length; i++) {
- buffer[i] = chars[i];
- }
- buffer[length] = '\0';
- return new TestResource(buffer);
-}
-
-
-static v8::Handle<Value> ExternalSymbolGetter(Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- CHECK(!name->Equals(v8_str("externalSymbol722")) || name->IsExternal());
- return v8::True();
-}
-
-
-static void ExternalSymbolSetter(Local<String> name,
- Local<Value> value,
- const AccessorInfo&) {
- ApiTestFuzzer::Fuzz();
- CHECK(!name->Equals(v8_str("externalSymbol722")) || name->IsExternal());
-}
-
-
-THREADED_TEST(ExternalSymbols) {
- TestResource::dispose_count = 0;
- v8::V8::SetExternalSymbolCallback(SymbolCallback);
- v8::HandleScope scope;
- LocalContext context;
- Local<ObjectTemplate> templ = ObjectTemplate::New();
- // Use a bizare name so that the name does not clash with names used
- // in natives files. If running with snapshots enabled, variable
- // names used in the native files will be normal symbols instead of
- // external ones. Also, make sure that the bizare name is used from
- // JavaScript code before using it from C++ code.
- Local<Value> value =
- CompileRun("var o = { externalSymbol722: 42 }; o.externalSymbol722");
- CHECK_EQ(42, value->Int32Value());
- templ->SetAccessor(v8_str("externalSymbol722"),
- ExternalSymbolGetter,
- ExternalSymbolSetter);
- context->Global()->Set(v8_str("obj"), templ->NewInstance());
- value = CompileRun("obj.externalSymbol722");
- CHECK_EQ(true, value->BooleanValue());
- value = CompileRun("obj.externalSymbol722 = 42");
- v8::V8::SetExternalSymbolCallback(NULL);
-}
-
-
// This test verifies that pre-compilation (aka preparsing) can be called
// without initializing the whole VM. Thus we cannot run this test in a
// multi-threaded setup.