OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |