From e718576d4fcbadca08f46f6a73cada36b0de31d8 Mon Sep 17 00:00:00 2001 From: "iposva@chromium.org" Date: Fri, 23 Jan 2009 17:22:23 +0000 Subject: [PATCH] Split handle scopes into an internal version and a version accessible through the API. This allows us to verify state on entry through the API. In this change verification in the API entry is checking that the current thread holds the V8 lock when a HandleScope is instantiated if a v8::Locker has ever been used by the V8 instance. Review URL: http://codereview.chromium.org/18707 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1140 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 45 ++++-------- src/api.cc | 108 ++++++++++++----------------- src/api.h | 53 +++----------- src/apiutils.h | 69 ++++++++++++++++++ src/factory.cc | 2 +- src/handles-inl.h | 7 +- src/handles.cc | 68 ++++++++++++++++++ src/handles.h | 73 ++++++++++++++++++- src/messages.cc | 2 +- src/v8threads.cc | 8 +++ tools/v8.xcodeproj/project.pbxproj | 2 + 11 files changed, 291 insertions(+), 146 deletions(-) create mode 100644 src/apiutils.h diff --git a/include/v8.h b/include/v8.h index 1876a547c..fc8b47a4f 100644 --- a/include/v8.h +++ b/include/v8.h @@ -396,19 +396,11 @@ template class EXPORT_INLINE Persistent : public Handle { */ class EXPORT HandleScope { public: - HandleScope() : previous_(current_), is_closed_(false) { - current_.extensions = 0; - } + HandleScope(); - ~HandleScope() { - // TODO(1245391): In a perfect world, there would be a way of not - // having to check for explicitly closed scopes maybe through - // subclassing HandleScope? - if (!is_closed_) RestorePreviousState(); - } + ~HandleScope(); /** - * TODO(1245391): Consider introducing a subclass for this. * Closes the handle scope and returns the value as a handle in the * previous scope, which is the new current scope after the call. */ @@ -432,6 +424,8 @@ class EXPORT HandleScope { void* operator new(size_t size); void operator delete(void*, size_t); + // This Data class is accessible internally through a typedef in the + // ImplementationUtilities class. class EXPORT Data { public: int extensions; @@ -443,31 +437,13 @@ class EXPORT HandleScope { } }; - static Data current_; - const Data previous_; - - /** - * Re-establishes the previous scope state. Should be called only - * once, and only for the current scope. - */ - void RestorePreviousState() { - if (current_.extensions > 0) DeleteExtensions(); - current_ = previous_; -#ifdef DEBUG - ZapRange(current_.next, current_.limit); -#endif - } + Data previous_; - // TODO(1245391): Consider creating a subclass for this. + // Allow for the active closing of HandleScopes which allows to pass a handle + // from the HandleScope being closed to the next top most HandleScope. bool is_closed_; void** RawClose(void** value); - /** Deallocates any extensions used by the current scope.*/ - static void DeleteExtensions(); - - // Zaps the handles in the half-open interval [start, end). - static void ZapRange(void** start, void** end); - friend class ImplementationUtilities; }; @@ -2284,10 +2260,17 @@ class EXPORT Locker { */ static bool IsLocked(); + /** + * Returns whether v8::Locker is being used by this V8 instance. + */ + static bool IsActive() { return active_; } + private: bool has_lock_; bool top_level_; + static bool active_; + // Disallow copying and assigning. Locker(const Locker&); void operator=(const Locker&); diff --git a/src/api.cc b/src/api.cc index 485a148ce..7fb9b4b91 100644 --- a/src/api.cc +++ b/src/api.cc @@ -36,6 +36,7 @@ #include "platform.h" #include "serialize.h" #include "snapshot.h" +#include "v8threads.h" namespace i = v8::internal; @@ -73,6 +74,15 @@ namespace v8 { } while (false) +#define API_ENTRY_CHECK(msg) \ + do { \ + if (v8::Locker::IsActive()) { \ + ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \ + msg, \ + "Entering the V8 API without proper locking in place"); \ + } \ + } while (false) + // --- D a t a t h a t i s s p e c i f i c t o a t h r e a d --- @@ -190,6 +200,19 @@ static void EnsureInitialized(const char* location) { } +ImplementationUtilities::HandleScopeData* + ImplementationUtilities::CurrentHandleScope() { + return &i::HandleScope::current_; +} + + +#ifdef DEBUG +void ImplementationUtilities::ZapHandleRange(void** begin, void** end) { + i::HandleScope::ZapRange(begin, end); +} +#endif + + v8::Handle ImplementationUtilities::Undefined() { if (IsDeadCheck("v8::Undefined()")) return v8::Handle(); EnsureInitialized("v8::Undefined()"); @@ -359,55 +382,26 @@ void V8::DisposeGlobal(void** obj) { // --- H a n d l e s --- -HandleScope::Data HandleScope::current_ = { -1, NULL, NULL }; +HandleScope::HandleScope() : is_closed_(false) { + API_ENTRY_CHECK("HandleScope::HandleScope"); + i::HandleScope::Enter(&previous_); +} -int HandleScope::NumberOfHandles() { - int n = thread_local.Blocks()->length(); - if (n == 0) return 0; - return ((n - 1) * i::kHandleBlockSize) + - (current_.next - thread_local.Blocks()->last()); +HandleScope::~HandleScope() { + if (!is_closed_) { + i::HandleScope::Leave(&previous_); + } } -void** v8::HandleScope::CreateHandle(void* value) { - void** result = current_.next; - if (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 (!ApiCheck(current_.extensions >= 0, - "v8::HandleScope::CreateHandle()", - "Cannot create a handle without a HandleScope")) { - return NULL; - } - // If there's more room in the last block, we use that. This is used - // for fast creation of scopes after scope barriers. - if (!thread_local.Blocks()->is_empty()) { - void** limit = &thread_local.Blocks()->last()[i::kHandleBlockSize]; - if (current_.limit != limit) { - current_.limit = limit; - } - } +int HandleScope::NumberOfHandles() { + return i::HandleScope::NumberOfHandles(); +} - // 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 = thread_local.GetSpareOrNewBlock(); - // Add the extension to the global list of blocks, but count the - // extension as part of the current scope. - thread_local.Blocks()->Add(result); - current_.extensions++; - current_.limit = &result[i::kHandleBlockSize]; - } - } - // Update the current next field, set the value in the created - // handle, and return the result. - ASSERT(result < current_.limit); - current_.next = result + 1; - *result = value; - return result; +void** v8::HandleScope::CreateHandle(void* value) { + return i::HandleScope::CreateHandle(value); } @@ -436,20 +430,6 @@ void Context::Exit() { } -void v8::HandleScope::DeleteExtensions() { - ASSERT(current_.extensions != 0); - thread_local.DeleteExtensions(current_.extensions); -} - - -void HandleScope::ZapRange(void** start, void** end) { - if (start == NULL) return; - for (void** p = start; p < end; p++) { - *p = reinterpret_cast(v8::internal::kHandleZapValue); - } -} - - void** v8::HandleScope::RawClose(void** value) { if (!ApiCheck(!is_closed_, "v8::HandleScope::Close()", @@ -461,7 +441,7 @@ void** v8::HandleScope::RawClose(void** value) { // Read the result before popping the handle block. i::Object* result = reinterpret_cast(*value); is_closed_ = true; - RestorePreviousState(); + i::HandleScope::Leave(&previous_); // Allocate a new handle on the previous handle block. i::Handle handle(result); @@ -2951,8 +2931,8 @@ char* HandleScopeImplementer::ArchiveThread(char* storage) { char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) { - ImplementationUtilities::HandleScopeData* current = - ImplementationUtilities::CurrentHandleScope(); + v8::ImplementationUtilities::HandleScopeData* current = + v8::ImplementationUtilities::CurrentHandleScope(); handle_scope_data_ = *current; memcpy(storage, this, sizeof(*this)); @@ -2975,7 +2955,7 @@ char* HandleScopeImplementer::RestoreThread(char* storage) { char* HandleScopeImplementer::RestoreThreadHelper(char* storage) { memcpy(this, storage, sizeof(*this)); - *ImplementationUtilities::CurrentHandleScope() = handle_scope_data_; + *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_; return storage + ArchiveSpacePerThread(); } @@ -2983,7 +2963,7 @@ char* HandleScopeImplementer::RestoreThreadHelper(char* storage) { void HandleScopeImplementer::Iterate( ObjectVisitor* v, List* blocks, - ImplementationUtilities::HandleScopeData* handle_data) { + v8::ImplementationUtilities::HandleScopeData* handle_data) { // Iterate over all handles in the blocks except for the last. for (int i = blocks->length() - 2; i >= 0; --i) { Object** block = @@ -3000,8 +2980,8 @@ void HandleScopeImplementer::Iterate( void HandleScopeImplementer::Iterate(ObjectVisitor* v) { - ImplementationUtilities::HandleScopeData* current = - ImplementationUtilities::CurrentHandleScope(); + v8::ImplementationUtilities::HandleScopeData* current = + v8::ImplementationUtilities::CurrentHandleScope(); Iterate(v, thread_local.Blocks(), current); } @@ -3010,7 +2990,7 @@ char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { HandleScopeImplementer* thread_local = reinterpret_cast(storage); List* blocks_of_archived_thread = thread_local->Blocks(); - ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread = + v8::ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread = &thread_local->handle_scope_data_; Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread); diff --git a/src/api.h b/src/api.h index f4cea8b6a..85b13ec9a 100644 --- a/src/api.h +++ b/src/api.h @@ -28,6 +28,7 @@ #ifndef V8_API_H_ #define V8_API_H_ +#include "apiutils.h" #include "factory.h" namespace v8 { @@ -159,45 +160,6 @@ class RegisteredExtension { }; -class ImplementationUtilities { - public: - static v8::Handle Undefined(); - static v8::Handle Null(); - static v8::Handle True(); - static v8::Handle False(); - - static int GetNameCount(ExtensionConfiguration* that) { - return that->name_count_; - } - - static const char** GetNames(ExtensionConfiguration* that) { - return that->names_; - } - - static v8::Arguments NewArguments(Local data, - Local holder, - Local callee, - bool is_construct_call, - void** argv, int argc) { - return v8::Arguments(data, holder, callee, is_construct_call, argv, argc); - } - - // Introduce an alias for the handle scope data to allow non-friends - // to access the HandleScope data. - typedef v8::HandleScope::Data HandleScopeData; - - static HandleScopeData* CurrentHandleScope() { - return &v8::HandleScope::current_; - } - -#ifdef DEBUG - static void ZapHandleRange(void** begin, void** end) { - v8::HandleScope::ZapRange(begin, end); - } -#endif -}; - - class Utils { public: static bool ReportApiFailure(const char* location, const char* message); @@ -275,7 +237,7 @@ static inline T* ToApi(v8::internal::Handle obj) { template v8::internal::Handle v8::internal::Handle::EscapeFrom( - HandleScope* scope) { + v8::HandleScope* scope) { return Utils::OpenHandle(*scope->Close(Utils::ToLocal(*this))); } @@ -408,11 +370,11 @@ class HandleScopeImplementer { List > saved_contexts_; bool ignore_out_of_memory; // This is only used for threading support. - ImplementationUtilities::HandleScopeData handle_scope_data_; + v8::ImplementationUtilities::HandleScopeData handle_scope_data_; static void Iterate(ObjectVisitor* v, - List* blocks, - ImplementationUtilities::HandleScopeData* handle_data); + List* blocks, + v8::ImplementationUtilities::HandleScopeData* handle_data); char* RestoreThreadHelper(char* from); char* ArchiveThreadHelper(char* to); @@ -474,13 +436,14 @@ void HandleScopeImplementer::DeleteExtensions(int extensions) { for (int i = extensions; i > 1; --i) { void** block = blocks.RemoveLast(); #ifdef DEBUG - ImplementationUtilities::ZapHandleRange(block, &block[kHandleBlockSize]); + v8::ImplementationUtilities::ZapHandleRange(block, + &block[kHandleBlockSize]); #endif DeleteArray(block); } spare = reinterpret_cast(blocks.RemoveLast()); #ifdef DEBUG - ImplementationUtilities::ZapHandleRange( + v8::ImplementationUtilities::ZapHandleRange( reinterpret_cast(spare), reinterpret_cast(&spare[kHandleBlockSize])); #endif diff --git a/src/apiutils.h b/src/apiutils.h new file mode 100644 index 000000000..57453438e --- /dev/null +++ b/src/apiutils.h @@ -0,0 +1,69 @@ +// Copyright 2009 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. + +#ifndef V8_APIUTILS_H_ +#define V8_APIUTILS_H_ + +namespace v8 { + +class ImplementationUtilities { + public: + static v8::Handle Undefined(); + static v8::Handle Null(); + static v8::Handle True(); + static v8::Handle False(); + + static int GetNameCount(ExtensionConfiguration* that) { + return that->name_count_; + } + + static const char** GetNames(ExtensionConfiguration* that) { + return that->names_; + } + + static v8::Arguments NewArguments(Local data, + Local holder, + Local callee, + bool is_construct_call, + void** argv, int argc) { + return v8::Arguments(data, holder, callee, is_construct_call, argv, argc); + } + + // Introduce an alias for the handle scope data to allow non-friends + // to access the HandleScope data. + typedef v8::HandleScope::Data HandleScopeData; + + static HandleScopeData* CurrentHandleScope(); + +#ifdef DEBUG + static void ZapHandleRange(void** begin, void** end); +#endif +}; + +} // namespace v8 + +#endif // V8_APIUTILS_H_ diff --git a/src/factory.cc b/src/factory.cc index c49f58a93..52d3bad9f 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -327,7 +327,7 @@ Handle Factory::NewReferenceError(Handle message) { Handle Factory::NewError(const char* maker, const char* type, Vector< Handle > args) { - HandleScope scope; + v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom. Handle array = Factory::NewFixedArray(args.length()); for (int i = 0; i < args.length(); i++) { array->set(i, *args[i]); diff --git a/src/handles-inl.h b/src/handles-inl.h index 0f804d7a9..e5899e3ac 100644 --- a/src/handles-inl.h +++ b/src/handles-inl.h @@ -29,6 +29,7 @@ #ifndef V8_HANDLES_INL_H_ #define V8_HANDLES_INL_H_ +#include "apiutils.h" #include "handles.h" #include "api.h" @@ -51,8 +52,8 @@ inline T* Handle::operator*() const { #ifdef DEBUG inline NoHandleAllocation::NoHandleAllocation() { - ImplementationUtilities::HandleScopeData* current = - ImplementationUtilities::CurrentHandleScope(); + v8::ImplementationUtilities::HandleScopeData* current = + v8::ImplementationUtilities::CurrentHandleScope(); extensions_ = current->extensions; // Shrink the current handle scope to make it impossible to do // handle allocations without an explicit handle scope. @@ -64,7 +65,7 @@ inline NoHandleAllocation::NoHandleAllocation() { inline NoHandleAllocation::~NoHandleAllocation() { // Restore state in current handle scope to re-enable handle // allocations. - ImplementationUtilities::CurrentHandleScope()->extensions = extensions_; + v8::ImplementationUtilities::CurrentHandleScope()->extensions = extensions_; } #endif diff --git a/src/handles.cc b/src/handles.cc index 58ba4728e..6f2a0447e 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -40,6 +40,74 @@ namespace v8 { namespace internal { +v8::ImplementationUtilities::HandleScopeData HandleScope::current_ = + { -1, NULL, NULL }; + + +int HandleScope::NumberOfHandles() { + int n = HandleScopeImplementer::instance()->Blocks()->length(); + if (n == 0) return 0; + return ((n - 1) * kHandleBlockSize) + + (current_.next - HandleScopeImplementer::instance()->Blocks()->last()); +} + + +void** HandleScope::CreateHandle(void* value) { + void** result = current_.next; + if (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 (current_.extensions < 0) { + Utils::ReportApiFailure("v8::HandleScope::CreateHandle()", + "Cannot create a handle without a HandleScope"); + return NULL; + } + HandleScopeImplementer* impl = HandleScopeImplementer::instance(); + // 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()) { + void** limit = &impl->Blocks()->last()[kHandleBlockSize]; + if (current_.limit != limit) { + current_.limit = limit; + } + } + + // 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_.extensions++; + current_.limit = &result[kHandleBlockSize]; + } + } + + // Update the current next field, set the value in the created + // handle, and return the result. + ASSERT(result < current_.limit); + current_.next = result + 1; + *result = value; + return result; +} + + +void HandleScope::DeleteExtensions() { + ASSERT(current_.extensions != 0); + HandleScopeImplementer::instance()->DeleteExtensions(current_.extensions); +} + + +void HandleScope::ZapRange(void** start, void** end) { + if (start == NULL) return; + for (void** p = start; p < end; p++) { + *p = reinterpret_cast(v8::internal::kHandleZapValue); + } +} + + Handle AddKeysFromJSArray(Handle content, Handle array) { CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray); diff --git a/src/handles.h b/src/handles.h index ec0614b5e..130af0215 100644 --- a/src/handles.h +++ b/src/handles.h @@ -28,12 +28,14 @@ #ifndef V8_HANDLES_H_ #define V8_HANDLES_H_ +#include "apiutils.h" + namespace v8 { namespace internal { // ---------------------------------------------------------------------------- // A Handle provides a reference to an object that survives relocation by // the garbage collector. -// Handles are only valid withing a HandleScope. +// Handles are only valid within a HandleScope. // When a handle is created for an object a cell is allocated in the heap. template @@ -90,6 +92,75 @@ class Handle { }; +// A stack-allocated class that governs a number of local handles. +// After a handle scope has been created, all local handles will be +// allocated within that handle scope until either the handle scope is +// deleted or another handle scope is created. If there is already a +// handle scope and a new one is created, all allocations will take +// place in the new handle scope until it is deleted. After that, +// new handles will again be allocated in the original handle scope. +// +// After the handle scope of a local handle has been deleted the +// garbage collector will no longer track the object stored in the +// handle and may deallocate it. The behavior of accessing a handle +// for which the handle scope has been deleted is undefined. +class HandleScope { + public: + HandleScope() : previous_(current_) { + current_.extensions = 0; + } + + ~HandleScope() { + Leave(&previous_); + } + + // Counts the number of allocated handles. + static int NumberOfHandles(); + + // Creates a new handle with the given value. + static void** CreateHandle(void* value); + + private: + // Prevent heap allocation or illegal handle scopes. + HandleScope(const HandleScope&); + void operator=(const HandleScope&); + void* operator new(size_t size); + void operator delete(void* size_t); + + static v8::ImplementationUtilities::HandleScopeData current_; + const v8::ImplementationUtilities::HandleScopeData previous_; + + // Pushes a fresh handle scope to be used when allocating new handles. + static void Enter( + v8::ImplementationUtilities::HandleScopeData* previous) { + *previous = current_; + current_.extensions = 0; + } + + // Re-establishes the previous scope state. Should be called only + // once, and only for the current scope. + static void Leave( + const v8::ImplementationUtilities::HandleScopeData* previous) { + if (current_.extensions > 0) { + DeleteExtensions(); + } + current_ = *previous; +#ifdef DEBUG + ZapRange(current_.next, current_.limit); +#endif + } + + // Deallocates any extensions used by the current scope. + static void DeleteExtensions(); + + // Zaps the handles in the half-open interval [start, end). + static void ZapRange(void** start, void** end); + + friend class v8::HandleScope; + friend class v8::ImplementationUtilities; +}; + + // ---------------------------------------------------------------------------- // Handle operations. // They might invoke garbage collection. The result is an handle to diff --git a/src/messages.cc b/src/messages.cc index e6a50842f..ca0ce2a54 100644 --- a/src/messages.cc +++ b/src/messages.cc @@ -66,7 +66,7 @@ Handle MessageHandler::MakeMessageObject( Vector< Handle > args, Handle stack_trace) { // Build error message object - HandleScope scope; + v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom. Handle type_str = Factory::LookupAsciiSymbol(type); Handle array = Factory::NewJSArray(args.length()); for (int i = 0; i < args.length(); i++) diff --git a/src/v8threads.cc b/src/v8threads.cc index 0a6c7c152..46be3d31d 100644 --- a/src/v8threads.cc +++ b/src/v8threads.cc @@ -38,9 +38,17 @@ namespace v8 { static internal::Thread::LocalStorageKey thread_state_key = internal::Thread::CreateThreadLocalKey(); + +// Track whether this V8 instance has ever called v8::Locker. This allows the +// API code to verify that the lock is always held when V8 is being entered. +bool Locker::active_ = false; + + // Constructor for the Locker object. Once the Locker is constructed the // current thread will be guaranteed to have the big V8 lock. Locker::Locker() : has_lock_(false), top_level_(true) { + // Record that the Locker has been used at least once. + active_ = true; // Get the big lock if necessary. if (!internal::ThreadManager::IsLockedByCurrentThread()) { internal::ThreadManager::Lock(); diff --git a/tools/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj index 8adfd0e23..685a86ca1 100644 --- a/tools/v8.xcodeproj/project.pbxproj +++ b/tools/v8.xcodeproj/project.pbxproj @@ -259,6 +259,7 @@ /* Begin PBXFileReference section */ 8900116B0E71CA2300F91F35 /* libraries.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = libraries.cc; sourceTree = ""; }; + 893986D40F29020C007D5254 /* apiutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apiutils.h; sourceTree = ""; }; 8944AD0E0F1D4D3A0028D560 /* regexp-stack.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "regexp-stack.cc"; sourceTree = ""; }; 8944AD0F0F1D4D3A0028D560 /* regexp-stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "regexp-stack.h"; sourceTree = ""; }; 89471C7F0EB23EE400B6874B /* flag-definitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "flag-definitions.h"; sourceTree = ""; }; @@ -595,6 +596,7 @@ 897FF0F90E719B8F00D62E90 /* allocation.h */, 897FF0FA0E719B8F00D62E90 /* api.cc */, 897FF0FB0E719B8F00D62E90 /* api.h */, + 893986D40F29020C007D5254 /* apiutils.h */, 897FF0FC0E719B8F00D62E90 /* arguments.h */, 897FF0FD0E719B8F00D62E90 /* assembler-arm-inl.h */, 897FF0FE0E719B8F00D62E90 /* assembler-arm.cc */, -- 2.34.1