Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: src/api-natives.cc

Issue 988283003: use a hash table for the function cache as blink is leaking functiontemplates (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/api-natives.h ('k') | src/bootstrapper.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/api-natives.h" 5 #include "src/api-natives.h"
6 #include "src/isolate-inl.h" 6 #include "src/isolate-inl.h"
7 7
8 namespace v8 { 8 namespace v8 {
9 namespace internal { 9 namespace internal {
10 10
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 } 200 }
201 auto object = isolate->factory()->NewJSObject(cons); 201 auto object = isolate->factory()->NewJSObject(cons);
202 ASSIGN_RETURN_ON_EXCEPTION( 202 ASSIGN_RETURN_ON_EXCEPTION(
203 isolate, result, ConfigureInstance(isolate, object, info), JSFunction); 203 isolate, result, ConfigureInstance(isolate, object, info), JSFunction);
204 // TODO(dcarney): is this necessary? 204 // TODO(dcarney): is this necessary?
205 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); 205 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
206 return scope.CloseAndEscape(result); 206 return scope.CloseAndEscape(result);
207 } 207 }
208 208
209 209
210 void InstallInCache(Isolate* isolate, int serial_number, 210 void CacheFunction(Isolate* isolate, Handle<Smi> serial_number,
211 Handle<JSFunction> function) { 211 Handle<JSFunction> function) {
212 auto cache = isolate->function_cache(); 212 auto cache = isolate->function_cache();
213 if (cache->length() <= serial_number) { 213 auto new_cache = ObjectHashTable::Put(cache, serial_number, function);
214 int new_size; 214 isolate->native_context()->set_function_cache(*new_cache);
215 if (isolate->next_serial_number() < 50) { 215 }
216 new_size = 100; 216
217 } else { 217
218 new_size = 3 * isolate->next_serial_number() / 2; 218 void UncacheFunction(Isolate* isolate, Handle<Smi> serial_number) {
219 } 219 auto cache = isolate->function_cache();
220 cache = FixedArray::CopySize(cache, new_size); 220 bool was_present = false;
221 isolate->native_context()->set_function_cache(*cache); 221 auto new_cache = ObjectHashTable::Remove(cache, serial_number, &was_present);
222 } 222 DCHECK(was_present);
223 cache->set(serial_number, *function); 223 isolate->native_context()->set_function_cache(*new_cache);
224 } 224 }
225 225
226 226
227 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, 227 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
228 Handle<FunctionTemplateInfo> data, 228 Handle<FunctionTemplateInfo> data,
229 Handle<Name> name) { 229 Handle<Name> name) {
230 int serial_number = Smi::cast(data->serial_number())->value(); 230 auto serial_number = handle(Smi::cast(data->serial_number()), isolate);
231 // Probe cache. 231 // Probe cache.
232 if (!data->do_not_cache()) { 232 if (!data->do_not_cache()) {
233 auto cache = isolate->function_cache(); 233 auto cache = isolate->function_cache();
234 // Fast case: see if the function has already been instantiated 234 Object* element = cache->Lookup(serial_number);
235 if (serial_number < cache->length()) { 235 if (element->IsJSFunction()) {
236 Handle<Object> element = FixedArray::get(cache, serial_number); 236 return handle(JSFunction::cast(element), isolate);
237 if (element->IsJSFunction()) {
238 return Handle<JSFunction>::cast(element);
239 }
240 } 237 }
241 } 238 }
242 // Enter a new scope. Recursion could otherwise create a lot of handles. 239 // Enter a new scope. Recursion could otherwise create a lot of handles.
243 HandleScope scope(isolate); 240 HandleScope scope(isolate);
244 Handle<JSObject> prototype; 241 Handle<JSObject> prototype;
245 if (!data->remove_prototype()) { 242 if (!data->remove_prototype()) {
246 auto prototype_templ = handle(data->prototype_template(), isolate); 243 auto prototype_templ = handle(data->prototype_template(), isolate);
247 if (prototype_templ->IsUndefined()) { 244 if (prototype_templ->IsUndefined()) {
248 prototype = isolate->factory()->NewJSObject(isolate->object_function()); 245 prototype = isolate->factory()->NewJSObject(isolate->object_function());
249 } else { 246 } else {
(...skipping 22 matching lines...) Expand all
272 isolate, JSObject::SetPrototype(prototype, parent_prototype, false), 269 isolate, JSObject::SetPrototype(prototype, parent_prototype, false),
273 JSFunction); 270 JSFunction);
274 } 271 }
275 } 272 }
276 auto function = ApiNatives::CreateApiFunction( 273 auto function = ApiNatives::CreateApiFunction(
277 isolate, data, prototype, ApiNatives::JavaScriptObjectType); 274 isolate, data, prototype, ApiNatives::JavaScriptObjectType);
278 if (!name.is_null() && name->IsString()) { 275 if (!name.is_null() && name->IsString()) {
279 function->shared()->set_name(*name); 276 function->shared()->set_name(*name);
280 } 277 }
281 if (!data->do_not_cache()) { 278 if (!data->do_not_cache()) {
282 // Cache the function to limit recursion. 279 // Cache the function.
283 InstallInCache(isolate, serial_number, function); 280 CacheFunction(isolate, serial_number, function);
284 } 281 }
285 auto result = ConfigureInstance(isolate, function, data); 282 auto result = ConfigureInstance(isolate, function, data);
286 if (result.is_null()) { 283 if (result.is_null()) {
287 // uncache on error. 284 // Uncache on error.
288 if (!data->do_not_cache()) { 285 if (!data->do_not_cache()) {
289 auto cache = isolate->function_cache(); 286 UncacheFunction(isolate, serial_number);
290 cache->set(serial_number, isolate->heap()->undefined_value());
291 } 287 }
292 return MaybeHandle<JSFunction>(); 288 return MaybeHandle<JSFunction>();
293 } 289 }
294 return scope.CloseAndEscape(function); 290 return scope.CloseAndEscape(function);
295 } 291 }
296 292
297 293
298 class InvokeScope { 294 class InvokeScope {
299 public: 295 public:
300 explicit InvokeScope(Isolate* isolate) 296 explicit InvokeScope(Isolate* isolate)
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i))); 575 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
580 JSObject::SetAccessor(result, accessor).Assert(); 576 JSObject::SetAccessor(result, accessor).Assert();
581 } 577 }
582 578
583 DCHECK(result->shared()->IsApiFunction()); 579 DCHECK(result->shared()->IsApiFunction());
584 return result; 580 return result;
585 } 581 }
586 582
587 } // namespace internal 583 } // namespace internal
588 } // namespace v8 584 } // namespace v8
OLDNEW
« no previous file with comments | « src/api-natives.h ('k') | src/bootstrapper.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698