Import Cobalt 3.11764
diff --git a/src/cobalt/base/base.gyp b/src/cobalt/base/base.gyp index a2822ab..19652ec 100644 --- a/src/cobalt/base/base.gyp +++ b/src/cobalt/base/base.gyp
@@ -45,6 +45,7 @@ 'log_message_handler.h', 'math.cc', 'math.h', + 'message_queue.h', 'poller.h', 'polymorphic_downcast.h', 'polymorphic_equatable.h',
diff --git a/src/cobalt/base/message_queue.h b/src/cobalt/base/message_queue.h new file mode 100644 index 0000000..3c7ad78 --- /dev/null +++ b/src/cobalt/base/message_queue.h
@@ -0,0 +1,63 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COBALT_BASE_MESSAGE_QUEUE_H_ +#define COBALT_BASE_MESSAGE_QUEUE_H_ + +#include <queue> +#include "base/callback.h" +#include "base/logging.h" +#include "base/synchronization/lock.h" + +namespace base { + +// A thread safe in-order message queue. In some situations this can be +// preferred versus PostTask()ing directly to a MessageLoop since the data +// stored within the queued Closures can be destroyed on demand, and also the +// queue messages can be processed at a time of the user's choosing. +class MessageQueue { + public: + ~MessageQueue() { + // Leave no message behind! + ProcessAll(); + } + + // Add a message to the end of the queue. + void AddMessage(const base::Closure& message) { + base::AutoLock lock(mutex_); + DCHECK(!message.is_null()); + queue_.push(message); + } + + // Execute all messages in the MessageQueue until the queue is empty and then + // return. + void ProcessAll() { + base::AutoLock lock(mutex_); + + while (!queue_.empty()) { + queue_.front().Run(); + queue_.pop(); + } + } + + private: + base::Lock mutex_; + std::queue<base::Closure> queue_; +}; + +} // namespace base + +#endif // COBALT_BASE_MESSAGE_QUEUE_H_
diff --git a/src/cobalt/bindings/testing/global_interface_bindings_test.cc b/src/cobalt/bindings/testing/global_interface_bindings_test.cc index 5f8b90c..5f50d61 100644 --- a/src/cobalt/bindings/testing/global_interface_bindings_test.cc +++ b/src/cobalt/bindings/testing/global_interface_bindings_test.cc
@@ -38,7 +38,9 @@ } // namespace TEST_F(GlobalInterfaceBindingsTest, GlobalWindowIsThis) { - EXPECT_TRUE(EvaluateScript("window === this;", NULL)); + std::string result; + EXPECT_TRUE(EvaluateScript("window === this;", &result)); + EXPECT_STREQ("true", result.c_str()); } TEST_F(GlobalInterfaceBindingsTest, GlobalOperation) {
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc index 692ee5d..da20704 100644 --- a/src/cobalt/browser/browser_module.cc +++ b/src/cobalt/browser/browser_module.cc
@@ -139,6 +139,9 @@ options.network_module_options), render_tree_combiner_(renderer_module_.pipeline(), renderer_module_.render_target()->GetSize()), +#if defined(ENABLE_SCREENSHOT) + screen_shot_writer_(new ScreenShotWriter(renderer_module_.pipeline())), +#endif // defined(ENABLE_SCREENSHOT) web_module_loaded_(true /* manually_reset */, false /* initially_signalled */), web_module_recreated_callback_(options.web_module_recreated_callback), @@ -158,9 +161,6 @@ kScreenshotCommandShortHelp, kScreenshotCommandLongHelp)), #endif // defined(ENABLE_SCREENSHOT) #endif // defined(ENABLE_DEBUG_CONSOLE) -#if defined(ENABLE_SCREENSHOT) - screen_shot_writer_(new ScreenShotWriter(renderer_module_.pipeline())), -#endif // defined(ENABLE_SCREENSHOT) ALLOW_THIS_IN_INITIALIZER_LIST( h5vcc_url_handler_(this, system_window, account_manager)), web_module_options_(options.web_module_options), @@ -190,7 +190,7 @@ #if defined(ENABLE_DEBUG_CONSOLE) debug_console_.reset(new DebugConsole( - base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced, + base::Bind(&BrowserModule::QueueOnDebugConsoleRenderTreeProduced, base::Unretained(this)), media_module_.get(), &network_module_, renderer_module_.render_target()->GetSize(), @@ -239,18 +239,19 @@ } // Destroy old WebModule first, so we don't get a memory high-watermark after - // the second WebModule's construtor runs, but before scoped_ptr::reset() is + // the second WebModule's constructor runs, but before scoped_ptr::reset() is // run. web_module_.reset(NULL); // Show a splash screen while we're waiting for the web page to load. const math::Size& viewport_size = renderer_module_.render_target()->GetSize(); DestroySplashScreen(); - splash_screen_.reset(new SplashScreen( - base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this)), - &network_module_, viewport_size, - renderer_module_.pipeline()->GetResourceProvider(), - kLayoutMaxRefreshFrequencyInHz)); + splash_screen_.reset( + new SplashScreen(base::Bind(&BrowserModule::QueueOnRenderTreeProduced, + base::Unretained(this)), + &network_module_, viewport_size, + renderer_module_.pipeline()->GetResourceProvider(), + kLayoutMaxRefreshFrequencyInHz)); // Create new WebModule. #if !defined(COBALT_FORCE_CSP) @@ -269,19 +270,27 @@ #endif // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR) options.image_cache_capacity_multiplier_when_playing_video = COBALT_IMAGE_CACHE_CAPACITY_MULTIPLIER_WHEN_PLAYING_VIDEO; - web_module_.reset(new WebModule( - url, - base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this)), - base::Bind(&BrowserModule::OnError, base::Unretained(this)), - media_module_.get(), &network_module_, viewport_size, - renderer_module_.pipeline()->GetResourceProvider(), - kLayoutMaxRefreshFrequencyInHz, options)); + web_module_.reset( + new WebModule(url, base::Bind(&BrowserModule::QueueOnRenderTreeProduced, + base::Unretained(this)), + base::Bind(&BrowserModule::OnError, base::Unretained(this)), + media_module_.get(), &network_module_, viewport_size, + renderer_module_.pipeline()->GetResourceProvider(), + kLayoutMaxRefreshFrequencyInHz, options)); if (!web_module_recreated_callback_.is_null()) { web_module_recreated_callback_.Run(); } } void BrowserModule::OnLoad() { + // Repost to our own message loop if necessary. This also prevents + // asynchonrous access to this object by |web_module_| during destruction. + if (MessageLoop::current() != self_message_loop_) { + self_message_loop_->PostTask( + FROM_HERE, base::Bind(&BrowserModule::OnLoad, weak_this_)); + return; + } + DestroySplashScreen(); web_module_loaded_.Signal(); } @@ -303,16 +312,28 @@ } #endif +void BrowserModule::ProcessRenderTreeSubmissionQueue() { + TRACE_EVENT0("cobalt::browser", + "BrowserModule::ProcessRenderTreeSubmissionQueue()"); + DCHECK_EQ(MessageLoop::current(), self_message_loop_); + render_tree_submission_queue_.ProcessAll(); +} + +void BrowserModule::QueueOnRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results) { + TRACE_EVENT0("cobalt::browser", "BrowserModule::QueueOnRenderTreeProduced()"); + render_tree_submission_queue_.AddMessage( + base::Bind(&BrowserModule::OnRenderTreeProduced, base::Unretained(this), + layout_results)); + self_message_loop_->PostTask( + FROM_HERE, + base::Bind(&BrowserModule::ProcessRenderTreeSubmissionQueue, weak_this_)); +} + void BrowserModule::OnRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results) { TRACE_EVENT0("cobalt::browser", "BrowserModule::OnRenderTreeProduced()"); - if (MessageLoop::current() != self_message_loop_) { - self_message_loop_->PostTask( - FROM_HERE, - base::Bind(&BrowserModule::OnRenderTreeProduced, weak_this_, - layout_results)); - return; - } + DCHECK_EQ(MessageLoop::current(), self_message_loop_); renderer::Submission renderer_submission(layout_results.render_tree, layout_results.layout_time); @@ -372,17 +393,23 @@ } } +void BrowserModule::QueueOnDebugConsoleRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results) { + TRACE_EVENT0("cobalt::browser", + "BrowserModule::QueueOnDebugConsoleRenderTreeProduced()"); + render_tree_submission_queue_.AddMessage( + base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced, + base::Unretained(this), layout_results)); + self_message_loop_->PostTask( + FROM_HERE, + base::Bind(&BrowserModule::ProcessRenderTreeSubmissionQueue, weak_this_)); +} + void BrowserModule::OnDebugConsoleRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results) { TRACE_EVENT0("cobalt::browser", "BrowserModule::OnDebugConsoleRenderTreeProduced()"); - if (MessageLoop::current() != self_message_loop_) { - self_message_loop_->PostTask( - FROM_HERE, - base::Bind(&BrowserModule::OnDebugConsoleRenderTreeProduced, weak_this_, - layout_results)); - return; - } + DCHECK_EQ(MessageLoop::current(), self_message_loop_); render_tree_combiner_.UpdateDebugConsoleRenderTree(renderer::Submission( layout_results.render_tree, layout_results.layout_time));
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h index df6da73..d00a3fb 100644 --- a/src/cobalt/browser/browser_module.h +++ b/src/cobalt/browser/browser_module.h
@@ -24,6 +24,7 @@ #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" #include "cobalt/account/account_manager.h" +#include "cobalt/base/message_queue.h" #include "cobalt/browser/h5vcc_url_handler.h" #include "cobalt/browser/render_tree_combiner.h" #include "cobalt/browser/screen_shot_writer.h" @@ -126,6 +127,8 @@ // Glue function to deal with the production of the main render tree, // and will manage handing it off to the renderer. + void QueueOnRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results); void OnRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results); @@ -173,6 +176,8 @@ // Glue function to deal with the production of the debug console render tree, // and will manage handing it off to the renderer. + void QueueOnDebugConsoleRenderTreeProduced( + const browser::WebModule::LayoutResults& layout_results); void OnDebugConsoleRenderTreeProduced( const browser::WebModule::LayoutResults& layout_results); #endif // defined(ENABLE_DEBUG_CONSOLE) @@ -192,6 +197,9 @@ void OnRendererSubmissionRasterized(); #endif // OS_STARBOARD + // Process all messages queued into the |render_tree_submission_queue_|. + void ProcessRenderTreeSubmissionQueue(); + // TODO: // WeakPtr usage here can be avoided if BrowserModule has a thread to // own where it can ensure that its tasks are all resolved when it is @@ -244,6 +252,18 @@ // Manages the two render trees, combines and renders them. RenderTreeCombiner render_tree_combiner_; +#if defined(ENABLE_SCREENSHOT) + // Helper object to create screen shots of the last layout tree. + scoped_ptr<ScreenShotWriter> screen_shot_writer_; +#endif // defined(ENABLE_SCREENSHOT) + + // Keeps track of all messages containing render tree submissions that will + // ultimately reference the |render_tree_combiner_| and the + // |renderer_module_|. It is important that this is destroyed before the + // above mentioned references are. It must however outlive all WebModules + // that may be producing render trees. + base::MessageQueue render_tree_submission_queue_; + // Sets up everything to do with web page management, from loading and // parsing the web page and all referenced files to laying it out. The // web module will ultimately produce a render tree that can be passed @@ -283,11 +303,6 @@ #endif // defined(ENABLE_SCREENSHOT) #endif // defined(ENABLE_DEBUG_CONSOLE) -#if defined(ENABLE_SCREENSHOT) - // Helper object to create screen shots of the last layout tree. - scoped_ptr<ScreenShotWriter> screen_shot_writer_; -#endif // defined(ENABLE_SCREENSHOT) - // Handler object for h5vcc URLs. H5vccURLHandler h5vcc_url_handler_;
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index eb49ee4..fa37d0f 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -11337 \ No newline at end of file +11764 \ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi index 3e07aab..56da0af 100644 --- a/src/cobalt/build/config/base.gypi +++ b/src/cobalt/build/config/base.gypi
@@ -122,6 +122,7 @@ # - scratch_surface_cache_size_in_bytes # - surface_cache_size_in_bytes # - image_cache_size_in_bytes + # - skia_glyph_atlas_width * skia_glyph_atlas_height # # The other caches affect CPU memory usage. @@ -162,6 +163,15 @@ # image_cache_capacity_multiplier_when_playing_video. 'image_cache_capacity_multiplier_when_playing_video%': '1.0f', + # Determines the size in pixels of the glyph atlas where rendered glyphs are + # cached. The resulting memory usage is 2 bytes of GPU memory per pixel. + # When a value is used that is too small, thrashing may occur that will + # result in visible stutter. Such thrashing is more likely to occur when CJK + # language glyphs are rendered and when the size of the glyphs in pixels is + # larger, such as for higher resolution displays. + 'skia_glyph_atlas_width%': '2048', + 'skia_glyph_atlas_height%': '2048', + # Compiler configuration. # The following variables are used to specify compiler and linker
diff --git a/src/cobalt/debug/debug_web_server.cc b/src/cobalt/debug/debug_web_server.cc index 0bc80b7..5ec3d06 100644 --- a/src/cobalt/debug/debug_web_server.cc +++ b/src/cobalt/debug/debug_web_server.cc
@@ -137,10 +137,10 @@ } DebugWebServer::~DebugWebServer() { - net::HttpServer* server = server_.get(); - server_->AddRef(); - server_ = NULL; - http_server_thread_.message_loop()->ReleaseSoon(FROM_HERE, server); + // Destroy the server on its own thread then stop the thread. + http_server_thread_.message_loop()->PostTask( + FROM_HERE, + base::Bind(&DebugWebServer::StopServer, base::Unretained(this))); http_server_thread_.Stop(); } @@ -320,5 +320,10 @@ } } +void DebugWebServer::StopServer() { + DCHECK(thread_checker_.CalledOnValidThread()); + server_ = NULL; +} + } // namespace debug } // namespace cobalt
diff --git a/src/cobalt/debug/debug_web_server.h b/src/cobalt/debug/debug_web_server.h index ac2a593..9f55c16 100644 --- a/src/cobalt/debug/debug_web_server.h +++ b/src/cobalt/debug/debug_web_server.h
@@ -79,11 +79,14 @@ void StartServer(int port); + void StopServer(); + void SendErrorResponseOverWebSocket(int id, const std::string& message); base::ThreadChecker thread_checker_; base::Thread http_server_thread_; scoped_ptr<net::StreamListenSocketFactory> factory_; + // net::HttpServer is a ref-counted object, so we have to use scoped_refptr. scoped_refptr<net::HttpServer> server_; GetDebugServerCallback get_debug_server_callback_;
diff --git a/src/cobalt/dom/media_error.h b/src/cobalt/dom/media_error.h index 339c386..124b437 100644 --- a/src/cobalt/dom/media_error.h +++ b/src/cobalt/dom/media_error.h
@@ -44,7 +44,7 @@ // Web API: MediaError // - Code code() const { return code_; } + uint32 code() const { return code_; } DEFINE_WRAPPABLE_TYPE(MediaError);
diff --git a/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc index e65ef8f..75e760b 100644 --- a/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc +++ b/src/cobalt/dom_parser/libxml_html_parser_wrapper.cc
@@ -110,9 +110,7 @@ return; } - if (!IsStringUTF8(std::string(data, size))) { - static const char* kWarningNotUTF8 = "Ignoring non-UTF8 HTML input."; - OnParsingIssue(kWarning, kWarningNotUTF8); + if (CheckInputAndUpdateSeverity(data, size) >= kError) { return; } @@ -127,7 +125,7 @@ NULL /*filename*/, XML_CHAR_ENCODING_UTF8); if (!html_parser_context_) { - static const char* kErrorUnableCreateParser = + static const char kErrorUnableCreateParser[] = "Unable to create the libxml2 parser."; OnParsingIssue(kFatal, kErrorUnableCreateParser); } else { @@ -149,12 +147,8 @@ } if (html_parser_context_) { - // TODO: The check on issue level is a workaround for the fact that libxml - // doesn't recover fully from error related to encoding. - if (issue_level() <= kWarning) { - htmlParseChunk(html_parser_context_, NULL, 0, - 1 /*terminate*/); // Triggers EndDocument - } + htmlParseChunk(html_parser_context_, NULL, 0, + 1 /*terminate*/); // Triggers EndDocument if (IsFullDocument()) { document()->DecreaseLoadingCounterAndMaybeDispatchLoadEvent(); }
diff --git a/src/cobalt/dom_parser/libxml_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_parser_wrapper.cc index 3acaf88..ec05383 100644 --- a/src/cobalt/dom_parser/libxml_parser_wrapper.cc +++ b/src/cobalt/dom_parser/libxml_parser_wrapper.cc
@@ -214,8 +214,8 @@ void LibxmlParserWrapper::OnParsingIssue(IssueSeverity severity, const std::string& message) { - if (severity > issue_level_) { - issue_level_ = severity; + if (severity > max_severity_) { + max_severity_ = severity; } if (severity < LibxmlParserWrapper::kFatal) { LOG(WARNING) << message; @@ -230,5 +230,31 @@ node_stack_.top()->AppendChild(new dom::CDATASection(document_, value)); } +LibxmlParserWrapper::IssueSeverity +LibxmlParserWrapper::CheckInputAndUpdateSeverity(const char* data, + size_t size) { + if (max_severity_ >= kError) { + return max_severity_; + } + + // Check the total input size. + total_input_size_ += size; + if (total_input_size_ > kMaxTotalInputSize) { + static const char kErrorTooLong[] = "Parser input is too long."; + OnParsingIssue(kError, kErrorTooLong); + return max_severity_; + } + + // Check the encoding of the input. + if (!IsStringUTF8(std::string(data, size))) { + static const char kErrorNotUTF8[] = + "Parser input contains non-UTF8 characters."; + OnParsingIssue(kError, kErrorNotUTF8); + return max_severity_; + } + + return max_severity_; +} + } // namespace dom_parser } // namespace cobalt
diff --git a/src/cobalt/dom_parser/libxml_parser_wrapper.h b/src/cobalt/dom_parser/libxml_parser_wrapper.h index 61f3d04..c391fab 100644 --- a/src/cobalt/dom_parser/libxml_parser_wrapper.h +++ b/src/cobalt/dom_parser/libxml_parser_wrapper.h
@@ -92,7 +92,8 @@ first_chunk_location_(first_chunk_location), error_callback_(error_callback), depth_limit_exceeded_(false), - issue_level_(kNoIssue) {} + max_severity_(kNoIssue), + total_input_size_(0) {} virtual ~LibxmlParserWrapper() {} // These functions are for Libxml interface, calls are forwarded here by @@ -120,6 +121,9 @@ // Returns true when the input is a full document, false when it's a fragment. bool IsFullDocument() { return document_ == parent_node_; } + // Checks the input, updates and returns the maximum issue severity. + IssueSeverity CheckInputAndUpdateSeverity(const char* data, size_t size); + const scoped_refptr<dom::Document>& document() { return document_; } const base::SourceLocation& first_chunk_location() { return first_chunk_location_; @@ -128,13 +132,14 @@ return error_callback_; } - IssueSeverity issue_level() const { return issue_level_; } - const std::stack<scoped_refptr<dom::Node> >& node_stack() { return node_stack_; } private: + // Maximum total input size, 1MB. + static const size_t kMaxTotalInputSize = 1 << 16; + const scoped_refptr<dom::Document> document_; const scoped_refptr<dom::Node> parent_node_; const scoped_refptr<dom::Node> reference_node_; @@ -145,7 +150,8 @@ const base::Callback<void(const std::string&)> error_callback_; bool depth_limit_exceeded_; - IssueSeverity issue_level_; + IssueSeverity max_severity_; + size_t total_input_size_; std::stack<scoped_refptr<dom::Node> > node_stack_;
diff --git a/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc b/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc index edab9f0..c933f5e 100644 --- a/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc +++ b/src/cobalt/dom_parser/libxml_xml_parser_wrapper.cc
@@ -79,9 +79,7 @@ return; } - if (!IsStringUTF8(std::string(data, size))) { - static const char* kWarningNotUTF8 = "Ignoring non-UTF8 XML input."; - OnParsingIssue(kWarning, kWarningNotUTF8); + if (CheckInputAndUpdateSeverity(data, size) >= kError) { return; }
diff --git a/src/cobalt/loader/embedded_resources/splash_screen.css b/src/cobalt/loader/embedded_resources/splash_screen.css index 0af40bf..7602576 100644 --- a/src/cobalt/loader/embedded_resources/splash_screen.css +++ b/src/cobalt/loader/embedded_resources/splash_screen.css
@@ -4,11 +4,11 @@ } #splash { - background-color: #e62d27; + background-color: #e62117; background-image: url("h5vcc-embedded://you_tube_logo.png"); background-position: center center; background-repeat: no-repeat; - background-size: 60%; + background-size: 100%; height: 100%; left: 0; position: absolute;
diff --git a/src/cobalt/loader/embedded_resources/you_tube_logo.png b/src/cobalt/loader/embedded_resources/you_tube_logo.png index 0d2082d..a964097 100644 --- a/src/cobalt/loader/embedded_resources/you_tube_logo.png +++ b/src/cobalt/loader/embedded_resources/you_tube_logo.png Binary files differ
diff --git a/src/cobalt/media/media_buffer_allocator.h b/src/cobalt/media/media_buffer_allocator.h new file mode 100644 index 0000000..ef7f620 --- /dev/null +++ b/src/cobalt/media/media_buffer_allocator.h
@@ -0,0 +1,89 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COBALT_MEDIA_MEDIA_BUFFER_ALLOCATOR_H_ +#define COBALT_MEDIA_MEDIA_BUFFER_ALLOCATOR_H_ + +#include "base/optional.h" +#include "nb/memory_pool.h" + +namespace cobalt { +namespace media { + +class MediaBufferAllocator { + public: + MediaBufferAllocator(void* pool, size_t main_pool_size, + size_t small_allocation_pool_size, + size_t small_allocation_threshold) + : pool_(reinterpret_cast<uint8*>(pool)), + main_pool_size_(main_pool_size), + small_allocation_pool_size_(small_allocation_pool_size), + small_allocation_threshold_(small_allocation_threshold), + main_pool_(pool_, main_pool_size_, true, /* thread_safe */ + true /* verify_full_capacity */) { + if (small_allocation_pool_size_ > 0u) { + DCHECK_GT(small_allocation_threshold_, 0u); + small_allocation_pool_.emplace(pool_ + main_pool_size_, + small_allocation_pool_size_, + true, /* thread_safe */ + true /* verify_full_capacity */); + } else { + DCHECK_EQ(small_allocation_pool_size_, 0u); + DCHECK_EQ(small_allocation_threshold_, 0u); + } + } + + void* Allocate(size_t size, size_t alignment) { + void* p = NULL; + if (size < small_allocation_threshold_ && small_allocation_pool_) { + p = small_allocation_pool_->Allocate(size, alignment); + } + if (!p) { + p = main_pool_.Allocate(size, alignment); + } + if (!p && small_allocation_pool_) { + p = small_allocation_pool_->Allocate(size, alignment); + } + return p; + } + + void Free(void* p) { + if (p >= pool_ + main_pool_size_ && small_allocation_pool_) { + DCHECK_LT(p, pool_ + main_pool_size_ + small_allocation_pool_size_); + small_allocation_pool_->Free(p); + return; + } + DCHECK_GE(p, pool_); + DCHECK_LT(p, pool_ + main_pool_size_); + main_pool_.Free(p); + } + + private: + uint8* pool_; + size_t main_pool_size_; + size_t small_allocation_pool_size_; + size_t small_allocation_threshold_; + + nb::MemoryPool main_pool_; + base::optional<nb::MemoryPool> small_allocation_pool_; + + DISALLOW_COPY_AND_ASSIGN(MediaBufferAllocator); +}; + +} // namespace media +} // namespace cobalt + +#endif // COBALT_MEDIA_MEDIA_BUFFER_ALLOCATOR_H_
diff --git a/src/cobalt/script/mozjs/conversion_helpers.h b/src/cobalt/script/mozjs/conversion_helpers.h index 3d54ec6..f5eca1e 100644 --- a/src/cobalt/script/mozjs/conversion_helpers.h +++ b/src/cobalt/script/mozjs/conversion_helpers.h
@@ -369,6 +369,10 @@ context, global_environment->wrapper_factory()->GetWrapperProxy(in_object)); DCHECK(object); + JS::RootedObject proxy_target(context, js::GetProxyTargetObject(object)); + if (JS_IsGlobalObject(proxy_target)) { + object = proxy_target; + } out_value.set(OBJECT_TO_JSVAL(object)); }
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp index b29d99b..6e856f5 100644 --- a/src/cobalt/script/mozjs/mozjs.gyp +++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -73,5 +73,30 @@ '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib', ], }, + + { + 'target_name': 'mozjs_engine_test', + 'type': '<(gtest_target_type)', + 'sources': [ + '<(DEPTH)/third_party/mozjs/test/jscustomallocator_test.cc', + ], + 'dependencies': [ + '<(DEPTH)/base/base.gyp:run_all_unittests', + '<(DEPTH)/testing/gtest.gyp:gtest', + '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib', + ], + }, + + { + 'target_name': 'mozjs_engine_test_deploy', + 'type': 'none', + 'dependencies': [ + 'mozjs_engine_test', + ], + 'variables': { + 'executable_name': 'mozjs_engine_test', + }, + 'includes': [ '../../../starboard/build/deploy.gypi' ], + }, ], }
diff --git a/src/cobalt/script/mozjs/mozjs_engine.cc b/src/cobalt/script/mozjs/mozjs_engine.cc index 1b79cf7..6c21306 100644 --- a/src/cobalt/script/mozjs/mozjs_engine.cc +++ b/src/cobalt/script/mozjs/mozjs_engine.cc
@@ -19,7 +19,10 @@ #include <algorithm> #include "base/logging.h" +#include "cobalt/base/c_val.h" +#include "cobalt/base/poller.h" #include "cobalt/script/mozjs/mozjs_global_environment.h" +#include "third_party/mozjs/cobalt_config/include/jscustomallocator.h" #include "third_party/mozjs/js/src/jsapi.h" namespace cobalt { @@ -38,6 +41,64 @@ CheckAccessStub, MozjsGlobalEnvironment::CheckEval }; + +#if defined(__LB_SHELL__FOR_RELEASE__) +const int kPollerPeriodMs = 2000; +#else // #if defined(__LB_SHELL__FOR_RELEASE__) +const int kPollerPeriodMs = 20; +#endif // #if defined(__LB_SHELL__FOR_RELEASE__) + +class EngineStats { + public: + EngineStats(); + + static EngineStats* GetInstance() { + return Singleton<EngineStats, + StaticMemorySingletonTraits<EngineStats> >::get(); + } + + void EngineCreated() { + base::AutoLock auto_lock(lock_); + ++engine_count_; + } + + void EngineDestroyed() { + base::AutoLock auto_lock(lock_); + --engine_count_; + } + + void Update() { + base::AutoLock auto_lock(lock_); + allocated_memory_ = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + mapped_memory_ = MemoryAllocatorReporter::Get()->GetCurrentBytesMapped(); + memory_sum_ = allocated_memory_ + mapped_memory_; + } + + private: + base::Lock lock_; + base::CVal<size_t, base::CValPublic> allocated_memory_; + base::CVal<size_t, base::CValPublic> mapped_memory_; + base::CVal<size_t, base::CValPublic> memory_sum_; + base::CVal<size_t> engine_count_; + + // Repeating timer to query the used bytes. + scoped_ptr<base::PollerWithThread> poller_; +}; + +EngineStats::EngineStats() + : allocated_memory_("Memory.JS.AllocatedMemory", 0, + "JS memory occupied by the Mozjs allocator."), + mapped_memory_("Memory.JS.MappedMemory", 0, "JS mapped memory."), + memory_sum_("Memory.JS", 0, + "Total memory occupied by the Mozjs allocator and heap."), + engine_count_("Count.JS.Engine", 0, + "Total JavaScript engine registered.") { + poller_.reset(new base::PollerWithThread( + base::Bind(&EngineStats::Update, base::Unretained(this)), + base::TimeDelta::FromMilliseconds(kPollerPeriodMs))); +} + } // namespace MozjsEngine::MozjsEngine() { @@ -68,10 +129,13 @@ // Callback to be called during garbage collection during the sweep phase. JS_SetFinalizeCallback(runtime_, &MozjsEngine::FinalizeCallback); + + EngineStats::GetInstance()->EngineCreated(); } MozjsEngine::~MozjsEngine() { DCHECK(thread_checker_.CalledOnValidThread()); + EngineStats::GetInstance()->EngineDestroyed(); JS_DestroyRuntime(runtime_); }
diff --git a/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h b/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h index b8d70d1..4dcd88e 100644 --- a/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h +++ b/src/third_party/mozjs/cobalt_config/include/jscustomallocator.h
@@ -12,7 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#ifndef gc_JSCUSTOMALLOCATOR_H +#define gc_JSCUSTOMALLOCATOR_H + +#include <algorithm> + #include "jstypes.h" +#include "memory_allocator_reporter.h" #include "starboard/memory.h" #include "starboard/string.h" @@ -20,25 +26,58 @@ #define JS_OOM_POSSIBLY_FAIL_REPORT(cx) do {} while(0) static JS_INLINE void* js_malloc(size_t bytes) { - return SbMemoryAllocate(bytes); -} - -static JS_INLINE void* js_calloc(size_t bytes) { - return SbMemoryCalloc(bytes, 1); + size_t reservation_bytes = AllocationMetadata::GetReservationBytes(bytes); + MemoryAllocatorReporter::Get()->UpdateAllocatedBytes(reservation_bytes); + void* metadata = SbMemoryAllocate(reservation_bytes); + AllocationMetadata::SetSizeToBaseAddress(metadata, reservation_bytes); + return AllocationMetadata::GetUserAddressFromBaseAddress(metadata); } static JS_INLINE void* js_calloc(size_t nmemb, size_t size) { - return SbMemoryCalloc(nmemb, size); + size_t total_size = nmemb * size; + void* memory = js_malloc(total_size); + if (memory) { + SbMemorySet(memory, 0, total_size); + } + return memory; } -static JS_INLINE void* js_realloc(void* p, size_t bytes) { - return SbMemoryReallocate(p, bytes); +static JS_INLINE void* js_calloc(size_t bytes) { + return js_calloc(bytes, 1); } static JS_INLINE void js_free(void* p) { - SbMemoryFree(p); + if (p == NULL) { + return; + } + + AllocationMetadata* metadata = + AllocationMetadata::GetMetadataFromUserAddress(p); + MemoryAllocatorReporter::Get()->UpdateAllocatedBytes(-static_cast<ssize_t>( + AllocationMetadata::GetSizeOfAllocationFromMetadata(metadata))); + SbMemoryFree(metadata); +} + +static JS_INLINE void* js_realloc(void* p, size_t bytes) { + AllocationMetadata* metadata = + AllocationMetadata::GetMetadataFromUserAddress(p); + size_t current_size = + AllocationMetadata::GetSizeOfAllocationFromMetadata(metadata); + size_t adjusted_size = AllocationMetadata::GetReservationBytes(bytes); + + MemoryAllocatorReporter::Get()->UpdateAllocatedBytes( + static_cast<ssize_t>(adjusted_size - current_size)); + void* new_ptr = SbMemoryReallocate(metadata, adjusted_size); + AllocationMetadata::SetSizeToBaseAddress(new_ptr, adjusted_size); + return AllocationMetadata::GetUserAddressFromBaseAddress(new_ptr); } static JS_INLINE char* js_strdup(char* s) { - return SbStringDuplicate(s); + size_t length = SbStringGetLength(s) + 1; + + char* new_ptr = reinterpret_cast<char*>(js_malloc(length)); + SbStringCopy(new_ptr, s, length); + return new_ptr; } + +#endif /* gc_JSCUSTOMALLOCATOR_H */
diff --git a/src/third_party/mozjs/js/src/gc/Memory.cpp b/src/third_party/mozjs/js/src/gc/Memory.cpp index b9e5199..9c55ba1 100644 --- a/src/third_party/mozjs/js/src/gc/Memory.cpp +++ b/src/third_party/mozjs/js/src/gc/Memory.cpp
@@ -7,6 +7,7 @@ #include "gc/Memory.h" #include "jscntxt.h" +#include "memory_allocator_reporter.h" #include "js/HeapAPI.h" @@ -324,13 +325,23 @@ JS_ASSERT(flags == 0); JS_ASSERT(fd == -1); JS_ASSERT(offset == 0); - return SbMemoryMap(length, prot, "mozjs::gc::MapMemory"); + + void* result = SbMemoryMap(length, prot, "mozjs::gc::MapMemory"); + if (result != SB_MEMORY_MAP_FAILED) { + MemoryAllocatorReporter::Get()->UpdateMappedBytes(length); + } + return result; } static inline bool UnmapMemory(void* region, size_t length) { - return SbMemoryUnmap(region, length); + bool success = SbMemoryUnmap(region, length); + if (success) { + MemoryAllocatorReporter::Get()->UpdateMappedBytes( + -static_cast<ssize_t>(length)); + } + return success; } #else
diff --git a/src/third_party/mozjs/js/src/jsstarboard-time.cpp b/src/third_party/mozjs/js/src/jsstarboard-time.cpp index d5049e2..92d309b 100644 --- a/src/third_party/mozjs/js/src/jsstarboard-time.cpp +++ b/src/third_party/mozjs/js/src/jsstarboard-time.cpp
@@ -15,8 +15,11 @@ #include "jsstarboard-time.h" #include "mozilla/Assertions.h" +#include "starboard/configuration.h" #include "unicode/timezone.h" +// If the Starboard platform has this quirk, do not use these functions. +#if !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT) SbTime getDSTOffset(int64_t utc_time_us) { // UDate is in milliseconds from the epoch. UDate udate = utc_time_us / kSbTimeMillisecond; @@ -41,4 +44,4 @@ delete current_zone; return raw_offset_ms * kSbTimeMillisecond; } - +#endif
diff --git a/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp b/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp new file mode 100644 index 0000000..93d42df --- /dev/null +++ b/src/third_party/mozjs/js/src/memory_allocator_reporter.cpp
@@ -0,0 +1,83 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "memory_allocator_reporter.h" + +#include "starboard/once.h" + +namespace { +// Control to initialize s_instance. +SbOnceControl s_instance_control = SB_ONCE_INITIALIZER; +MemoryAllocatorReporter* s_instance = NULL; + +void Initialize() { + s_instance = new MemoryAllocatorReporter(); +} + +void* OffsetPointer(void* base, ssize_t offset) { + uintptr_t base_as_int = reinterpret_cast<uintptr_t>(base); + return reinterpret_cast<void*>(base_as_int + offset); +} +} // namespace + +AllocationMetadata* AllocationMetadata::GetMetadataFromUserAddress(void* ptr) { + if (ptr == NULL) { + return NULL; + } + + // The metadata lives just in front of the data. + void* meta_addr = + OffsetPointer(ptr, -static_cast<ssize_t>(sizeof(AllocationMetadata))); + return reinterpret_cast<AllocationMetadata*>(meta_addr); +} + +void* AllocationMetadata::GetUserAddressFromBaseAddress(void* base_ptr) { + void* adjusted_base = + OffsetPointer(base_ptr, static_cast<ssize_t>(sizeof(AllocationMetadata))); + return adjusted_base; +} + +void AllocationMetadata::SetSizeToBaseAddress(void* base_ptr, size_t size) { + if (base_ptr) { + AllocationMetadata* metadata = + reinterpret_cast<AllocationMetadata*>(base_ptr); + metadata->set_size_requested(size); + } +} + +void MemoryAllocatorReporter::UpdateAllocatedBytes(ssize_t bytes) { + starboard::ScopedLock lock(mutex_); + current_bytes_allocated_ += bytes; +} + +ssize_t MemoryAllocatorReporter::GetCurrentBytesAllocated() { + starboard::ScopedLock lock(mutex_); + return current_bytes_allocated_; +} + +void MemoryAllocatorReporter::UpdateMappedBytes(ssize_t bytes) { + starboard::ScopedLock lock(mutex_); + current_bytes_mapped_ += bytes; +} + +ssize_t MemoryAllocatorReporter::GetCurrentBytesMapped() { + starboard::ScopedLock lock(mutex_); + return current_bytes_mapped_; +} + +// static +MemoryAllocatorReporter* MemoryAllocatorReporter::Get() { + SbOnce(&s_instance_control, &Initialize); + return s_instance; +}
diff --git a/src/third_party/mozjs/js/src/memory_allocator_reporter.h b/src/third_party/mozjs/js/src/memory_allocator_reporter.h new file mode 100644 index 0000000..e0d679f --- /dev/null +++ b/src/third_party/mozjs/js/src/memory_allocator_reporter.h
@@ -0,0 +1,62 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef MemoryAllocatorReporter_h +#define MemoryAllocatorReporter_h + +#include <sys/types.h> + +#include "starboard/mutex.h" + +class AllocationMetadata { + public: + static AllocationMetadata* GetMetadataFromUserAddress(void* ptr); + static void* GetUserAddressFromBaseAddress(void* base_ptr); + static size_t GetReservationBytes(size_t bytes_requested) { + return sizeof(AllocationMetadata) + bytes_requested; + } + static size_t GetSizeOfAllocationFromMetadata(AllocationMetadata* metadata) { + return metadata ? metadata->size_requested() : 0; + } + static void SetSizeToBaseAddress(void* base_ptr, size_t size); + + size_t size_requested() { return size_requested_; } + void set_size_requested(size_t size) { size_requested_ = size; } + + private: + // Bytes requested by the underlying allocator. + size_t size_requested_; +}; + +// Reporter that is used to report memory allocation. +class MemoryAllocatorReporter { + public: + static MemoryAllocatorReporter* Get(); + + MemoryAllocatorReporter() + : current_bytes_allocated_(0), current_bytes_mapped_(0) {} + + void UpdateAllocatedBytes(ssize_t bytes); + ssize_t GetCurrentBytesAllocated(); + + void UpdateMappedBytes(ssize_t bytes); + ssize_t GetCurrentBytesMapped(); + + private: + starboard::Mutex mutex_; + ssize_t current_bytes_allocated_; + ssize_t current_bytes_mapped_; +}; + +#endif /* MemoryAllocatorReporter_h */
diff --git a/src/third_party/mozjs/js/src/vm/DateTime.cpp b/src/third_party/mozjs/js/src/vm/DateTime.cpp index cfca247..a78a121 100644 --- a/src/third_party/mozjs/js/src/vm/DateTime.cpp +++ b/src/third_party/mozjs/js/src/vm/DateTime.cpp
@@ -8,8 +8,16 @@ #if defined(STARBOARD) #include "jsstarboard-time.h" +#include "starboard/configuration.h" #include "starboard/time_zone.h" -#else +// For Starboard platforms that don't have support for getting the timezone +// name, fall back to using localtime for conversion between UTC<->localtime. +#if !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT) +#define USE_STARBOARD_TIME +#endif // !SB_HAS_QUIRK(NO_TIMEZONE_NAME_SUPPORT) +#endif // defined(STARBOARD) + +#if !defined(USE_STARBOARD_TIME) #include <time.h> #endif @@ -17,7 +25,7 @@ using mozilla::UnspecifiedNaN; -#if !defined(STARBOARD) +#if !defined(USE_STARBOARD_TIME) static bool ComputeLocalTime(time_t local, struct tm *ptm) { @@ -131,7 +139,7 @@ // local seconds' frame of reference and then subtract. return local_secs - (utc_secs + SecondsPerDay); } -#endif // defined(STARBOARD) +#endif // defined(USE_STARBOARD_TIME) void js::DateTimeInfo::updateTimeZoneAdjustment() @@ -140,7 +148,7 @@ * The difference between local standard time and UTC will never change for * a given time zone. */ -#if defined(STARBOARD) +#if defined(USE_STARBOARD_TIME) utcToLocalStandardOffsetSeconds = getTZOffset() / kSbTimeSecond; #else utcToLocalStandardOffsetSeconds = UTCToLocalStandardOffsetSeconds(); @@ -179,7 +187,7 @@ updateTimeZoneAdjustment(); } -#if defined(STARBOARD) +#if defined(USE_STARBOARD_TIME) int64_t js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t utcSeconds) { @@ -219,7 +227,7 @@ return diff * msPerSecond; } -#endif // defined(STARBOARD) +#endif // defined(USE_STARBOARD_TIME) int64_t js::DateTimeInfo::getDSTOffsetMilliseconds(int64_t utcMilliseconds)
diff --git a/src/third_party/mozjs/mozjs.gypi b/src/third_party/mozjs/mozjs.gypi index 9fb9822..6b85ee0 100644 --- a/src/third_party/mozjs/mozjs.gypi +++ b/src/third_party/mozjs/mozjs.gypi
@@ -82,6 +82,7 @@ 'js/src/jsweakmap.cpp', 'js/src/jsworkers.cpp', 'js/src/jswrapper.cpp', + 'js/src/memory_allocator_reporter.cpp', 'js/src/perf/jsperf.cpp', 'js/src/perf/pm_stub.cpp', 'js/src/prmjtime.cpp',
diff --git a/src/third_party/mozjs/test/jscustomallocator_test.cc b/src/third_party/mozjs/test/jscustomallocator_test.cc new file mode 100644 index 0000000..e6702e1 --- /dev/null +++ b/src/third_party/mozjs/test/jscustomallocator_test.cc
@@ -0,0 +1,178 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jscustomallocator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const size_t kSize = 1024 * 128; + +TEST(JSCustomallocator, JSMalloc) { + void* memory = js_malloc(kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + js_free(memory); + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSCallocWithNumber) { + void* memory = js_calloc(5, kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(5 * kSize)); + js_free(memory); + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSCalloc) { + void* memory = js_calloc(kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + js_free(memory); + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSReallocSmaller) { + void* memory = js_malloc(kSize); + ASSERT_NE(static_cast<void*>(NULL), memory); + char* data = static_cast<char*>(memory); + for (int i = 0; i < kSize; ++i) { + data[i] = i; + } + + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + + memory = js_realloc(memory, kSize / 2); + data = static_cast<char*>(memory); + ASSERT_NE(static_cast<void*>(NULL), memory); + for (int i = 0; i < kSize / 2; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize / 2)); + + js_free(memory); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSReallocBigger) { + void* memory = js_malloc(kSize); + ASSERT_NE(static_cast<void*>(NULL), memory); + char* data = static_cast<char*>(memory); + for (int i = 0; i < kSize; ++i) { + data[i] = i; + } + + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + + memory = js_realloc(memory, kSize * 2); + ASSERT_NE(static_cast<void*>(NULL), memory); + data = static_cast<char*>(memory); + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + for (int i = kSize; i < kSize * 2; ++i) { + data[i] = i; + } + + for (int i = kSize; i < kSize * 2; ++i) { + EXPECT_EQ(data[i], static_cast<char>(i)); + } + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize * 2)); + + js_free(memory); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSReallocNULL) { + void* memory = js_realloc(NULL, kSize); + EXPECT_NE(static_cast<void*>(NULL), memory); + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, + AllocationMetadata::GetReservationBytes(kSize)); + + js_free(memory); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +TEST(JSCustomallocator, JSStrdup) { + const char* input = "abcedfg123456"; + char* dupe = js_strdup(const_cast<char*>(input)); + const char* kNull = NULL; + EXPECT_NE(kNull, dupe); + EXPECT_EQ(0, SbStringCompareNoCase(input, dupe)); + EXPECT_EQ(SbStringGetLength(input), SbStringGetLength(dupe)); + + ssize_t current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, AllocationMetadata::GetReservationBytes( + SbStringGetLength(dupe) + 1)); + + js_free(dupe); + + current_bytes_allocated = + MemoryAllocatorReporter::Get()->GetCurrentBytesAllocated(); + EXPECT_EQ(current_bytes_allocated, 0); +} + +} // namespace
diff --git a/src/third_party/skia/gyp/gpu.gypi b/src/third_party/skia/gyp/gpu.gypi index ebc07b2..eaaf5d0 100644 --- a/src/third_party/skia/gyp/gpu.gypi +++ b/src/third_party/skia/gyp/gpu.gypi
@@ -6,6 +6,10 @@ # The skia build defines these in common_variables.gypi # { + 'defines': [ + 'COBALT_SKIA_GLYPH_ATLAS_WIDTH=<(skia_glyph_atlas_width)', + 'COBALT_SKIA_GLYPH_ATLAS_HEIGHT=<(skia_glyph_atlas_height)', + ], 'variables': { 'skgpu_sources': [ '<(skia_include_path)/gpu/GrBackendProcessorFactory.h',
diff --git a/src/third_party/skia/src/gpu/GrTextStrike.cpp b/src/third_party/skia/src/gpu/GrTextStrike.cpp index 66aeee0..ef1bf64 100644 --- a/src/third_party/skia/src/gpu/GrTextStrike.cpp +++ b/src/third_party/skia/src/gpu/GrTextStrike.cpp
@@ -19,8 +19,8 @@ // On Cobalt we would like to avoid re-rasterizing glyphs as much as possible, // so increase the default atlas size. -#define GR_ATLAS_TEXTURE_WIDTH 2048 -#define GR_ATLAS_TEXTURE_HEIGHT 2048 +#define GR_ATLAS_TEXTURE_WIDTH COBALT_SKIA_GLYPH_ATLAS_WIDTH +#define GR_ATLAS_TEXTURE_HEIGHT COBALT_SKIA_GLYPH_ATLAS_HEIGHT // On Cobalt, not being able to fit glyphs into the atlas is a big penalty, // since its software rendering is not optimized. Increase the plot size