// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "v8.h" #include "accessors.h" #include "api.h" #include "arguments.h" #include "bootstrapper.h" #include "compiler.h" #include "debug.h" #include "execution.h" #include "global-handles.h" #include "natives.h" #include "runtime.h" #include "string-search.h" #include "stub-cache.h" #include "vm-state-inl.h" namespace v8 { namespace internal { int HandleScope::NumberOfHandles(Isolate* isolate) { HandleScopeImplementer* impl = isolate->handle_scope_implementer(); int n = impl->blocks()->length(); if (n == 0) return 0; return ((n - 1) * kHandleBlockSize) + static_cast( (isolate->handle_scope_data()->next - impl->blocks()->last())); } Object** HandleScope::Extend(Isolate* isolate) { HandleScopeData* current = isolate->handle_scope_data(); Object** result = current->next; ASSERT(result == current->limit); // Make sure there's at least one scope on the stack and that the // top of the scope stack isn't a barrier. if (!Utils::ApiCheck(current->level != 0, "v8::HandleScope::CreateHandle()", "Cannot create a handle without a HandleScope")) { return NULL; } HandleScopeImplementer* impl = isolate->handle_scope_implementer(); // If there's more room in the last block, we use that. This is used // for fast creation of scopes after scope barriers. if (!impl->blocks()->is_empty()) { Object** limit = &impl->blocks()->last()[kHandleBlockSize]; if (current->limit != limit) { current->limit = limit; ASSERT(limit - current->next < kHandleBlockSize); } } // If we still haven't found a slot for the handle, we extend the // current handle scope by allocating a new handle block. if (result == current->limit) { // If there's a spare block, use it for growing the current scope. result = impl->GetSpareOrNewBlock(); // Add the extension to the global list of blocks, but count the // extension as part of the current scope. impl->blocks()->Add(result); current->limit = &result[kHandleBlockSize]; } return result; } void HandleScope::DeleteExtensions(Isolate* isolate) { HandleScopeData* current = isolate->handle_scope_data(); isolate->handle_scope_implementer()->DeleteExtensions(current->limit); } #ifdef ENABLE_HANDLE_ZAPPING void HandleScope::ZapRange(Object** start, Object** end) { ASSERT(end - start <= kHandleBlockSize); for (Object** p = start; p != end; p++) { *reinterpret_cast(p) = v8::internal::kHandleZapValue; } } #endif Address HandleScope::current_level_address(Isolate* isolate) { return reinterpret_cast
(&isolate->handle_scope_data()->level); } Address HandleScope::current_next_address(Isolate* isolate) { return reinterpret_cast
(&isolate->handle_scope_data()->next); } Address HandleScope::current_limit_address(Isolate* isolate) { return reinterpret_cast
(&isolate->handle_scope_data()->limit); } Handle AddKeysFromJSArray(Handle content, Handle array) { CALL_HEAP_FUNCTION(content->GetIsolate(), content->AddKeysFromJSArray(*array), FixedArray); } Handle UnionOfKeys(Handle first, Handle second) { CALL_HEAP_FUNCTION(first->GetIsolate(), first->UnionOfKeys(*second), FixedArray); } Handle ReinitializeJSGlobalProxy( Handle constructor, Handle global) { CALL_HEAP_FUNCTION( constructor->GetIsolate(), constructor->GetHeap()->ReinitializeJSGlobalProxy(*constructor, *global), JSGlobalProxy); } void FlattenString(Handle string) { CALL_HEAP_FUNCTION_VOID(string->GetIsolate(), string->TryFlatten()); } Handle FlattenGetString(Handle string) { CALL_HEAP_FUNCTION(string->GetIsolate(), string->TryFlatten(), String); } Handle ForceSetProperty(Handle object, Handle key, Handle value, PropertyAttributes attributes) { return Runtime::ForceSetObjectProperty(object->GetIsolate(), object, key, value, attributes); } Handle DeleteProperty(Handle object, Handle key) { Isolate* isolate = object->GetIsolate(); CALL_HEAP_FUNCTION(isolate, Runtime::DeleteObjectProperty( isolate, object, key, JSReceiver::NORMAL_DELETION), Object); } Handle ForceDeleteProperty(Handle object, Handle key) { Isolate* isolate = object->GetIsolate(); CALL_HEAP_FUNCTION(isolate, Runtime::DeleteObjectProperty( isolate, object, key, JSReceiver::FORCE_DELETION), Object); } Handle HasProperty(Handle obj, Handle key) { Isolate* isolate = obj->GetIsolate(); CALL_HEAP_FUNCTION(isolate, Runtime::HasObjectProperty(isolate, obj, key), Object); } Handle GetProperty(Handle obj, const char* name) { Isolate* isolate = obj->GetIsolate(); Handle str = isolate->factory()->InternalizeUtf8String(name); CALL_HEAP_FUNCTION(isolate, obj->GetProperty(*str), Object); } Handle GetProperty(Isolate* isolate, Handle obj, Handle key) { CALL_HEAP_FUNCTION(isolate, Runtime::GetObjectProperty(isolate, obj, key), Object); } Handle LookupSingleCharacterStringFromCode(Isolate* isolate, uint32_t index) { CALL_HEAP_FUNCTION( isolate, isolate->heap()->LookupSingleCharacterStringFromCode(index), String); } // Wrappers for scripts are kept alive and cached in weak global // handles referred from foreign objects held by the scripts as long as // they are used. When they are not used anymore, the garbage // collector will call the weak callback on the global handle // associated with the wrapper and get rid of both the wrapper and the // handle. static void ClearWrapperCache( const v8::WeakCallbackData& data) { Object** location = reinterpret_cast(data.GetParameter()); JSValue* wrapper = JSValue::cast(*location); Foreign* foreign = Script::cast(wrapper->value())->wrapper(); ASSERT_EQ(foreign->foreign_address(), reinterpret_cast
(location)); foreign->set_foreign_address(0); GlobalHandles::Destroy(location); Isolate* isolate = reinterpret_cast(data.GetIsolate()); isolate->counters()->script_wrappers()->Decrement(); } Handle GetScriptWrapper(Handle