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

Side by Side Diff: src/bootstrapper.cc

Issue 1722003: Added ability to remove prototype from function. In this case, [[Construct]] ... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Fixes according to Erik's comments Created 10 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/contexts.h » ('j') | test/mjsunit/function-without-prototype.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 Handle<ObjectTemplateInfo> object_template); 241 Handle<ObjectTemplateInfo> object_template);
242 bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template); 242 bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);
243 243
244 // Migrates all properties from the 'from' object to the 'to' 244 // Migrates all properties from the 'from' object to the 'to'
245 // object and overrides the prototype in 'to' with the one from 245 // object and overrides the prototype in 'to' with the one from
246 // 'from'. 246 // 'from'.
247 void TransferObject(Handle<JSObject> from, Handle<JSObject> to); 247 void TransferObject(Handle<JSObject> from, Handle<JSObject> to);
248 void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to); 248 void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
249 void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to); 249 void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);
250 250
251 enum PrototypePropertyMode {
252 DONT_ADD_PROTOTYPE,
253 ADD_READONLY_PROTOTYPE,
254 ADD_WRITEABLE_PROTOTYPE
255 };
251 Handle<DescriptorArray> ComputeFunctionInstanceDescriptor( 256 Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
252 bool make_prototype_read_only, 257 PrototypePropertyMode prototypeMode);
253 bool make_prototype_enumerable = false);
254 void MakeFunctionInstancePrototypeWritable(); 258 void MakeFunctionInstancePrototypeWritable();
255 259
256 static bool CompileBuiltin(int index); 260 static bool CompileBuiltin(int index);
257 static bool CompileNative(Vector<const char> name, Handle<String> source); 261 static bool CompileNative(Vector<const char> name, Handle<String> source);
258 static bool CompileScriptCached(Vector<const char> name, 262 static bool CompileScriptCached(Vector<const char> name,
259 Handle<String> source, 263 Handle<String> source,
260 SourceCodeCache* cache, 264 SourceCodeCache* cache,
261 v8::Extension* extension, 265 v8::Extension* extension,
262 Handle<Context> top_context, 266 Handle<Context> top_context,
263 bool use_runtime_context); 267 bool use_runtime_context);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 327
324 static Handle<JSFunction> InstallFunction(Handle<JSObject> target, 328 static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
325 const char* name, 329 const char* name,
326 InstanceType type, 330 InstanceType type,
327 int instance_size, 331 int instance_size,
328 Handle<JSObject> prototype, 332 Handle<JSObject> prototype,
329 Builtins::Name call, 333 Builtins::Name call,
330 bool is_ecma_native) { 334 bool is_ecma_native) {
331 Handle<String> symbol = Factory::LookupAsciiSymbol(name); 335 Handle<String> symbol = Factory::LookupAsciiSymbol(name);
332 Handle<Code> call_code = Handle<Code>(Builtins::builtin(call)); 336 Handle<Code> call_code = Handle<Code>(Builtins::builtin(call));
333 Handle<JSFunction> function = 337 Handle<JSFunction> function = prototype.is_null() ?
338 Factory::NewFunctionWithoutPrototype(symbol, call_code) :
334 Factory::NewFunctionWithPrototype(symbol, 339 Factory::NewFunctionWithPrototype(symbol,
335 type, 340 type,
336 instance_size, 341 instance_size,
337 prototype, 342 prototype,
338 call_code, 343 call_code,
339 is_ecma_native); 344 is_ecma_native);
340 SetProperty(target, symbol, function, DONT_ENUM); 345 SetProperty(target, symbol, function, DONT_ENUM);
341 if (is_ecma_native) { 346 if (is_ecma_native) {
342 function->shared()->set_instance_class_name(*symbol); 347 function->shared()->set_instance_class_name(*symbol);
343 } 348 }
344 return function; 349 return function;
345 } 350 }
346 351
347 352
348 Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor( 353 Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
349 bool make_prototype_read_only, 354 PrototypePropertyMode prototypeMode) {
350 bool make_prototype_enumerable) {
351 Handle<DescriptorArray> result = Factory::empty_descriptor_array(); 355 Handle<DescriptorArray> result = Factory::empty_descriptor_array();
352 356
353 // Add prototype. 357 if (prototypeMode != DONT_ADD_PROTOTYPE) {
354 PropertyAttributes attributes = static_cast<PropertyAttributes>( 358 PropertyAttributes attributes = static_cast<PropertyAttributes>(
355 (make_prototype_enumerable ? 0 : DONT_ENUM) 359 DONT_ENUM |
356 | DONT_DELETE 360 DONT_DELETE |
357 | (make_prototype_read_only ? READ_ONLY : 0)); 361 (prototypeMode == ADD_READONLY_PROTOTYPE ? READ_ONLY : 0));
358 result = 362 result =
359 Factory::CopyAppendProxyDescriptor( 363 Factory::CopyAppendProxyDescriptor(
360 result, 364 result,
361 Factory::prototype_symbol(), 365 Factory::prototype_symbol(),
362 Factory::NewProxy(&Accessors::FunctionPrototype), 366 Factory::NewProxy(&Accessors::FunctionPrototype),
363 attributes); 367 attributes);
368 }
364 369
365 attributes = 370 PropertyAttributes attributes =
366 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); 371 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
367 // Add length. 372 // Add length.
368 result = 373 result =
369 Factory::CopyAppendProxyDescriptor( 374 Factory::CopyAppendProxyDescriptor(
370 result, 375 result,
371 Factory::length_symbol(), 376 Factory::length_symbol(),
372 Factory::NewProxy(&Accessors::FunctionLength), 377 Factory::NewProxy(&Accessors::FunctionLength),
373 attributes); 378 attributes);
374 379
375 // Add name. 380 // Add name.
(...skipping 24 matching lines...) Expand all
400 } 405 }
401 406
402 407
403 Handle<JSFunction> Genesis::CreateEmptyFunction() { 408 Handle<JSFunction> Genesis::CreateEmptyFunction() {
404 // Allocate the map for function instances. 409 // Allocate the map for function instances.
405 Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); 410 Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
406 global_context()->set_function_instance_map(*fm); 411 global_context()->set_function_instance_map(*fm);
407 // Please note that the prototype property for function instances must be 412 // Please note that the prototype property for function instances must be
408 // writable. 413 // writable.
409 Handle<DescriptorArray> function_map_descriptors = 414 Handle<DescriptorArray> function_map_descriptors =
410 ComputeFunctionInstanceDescriptor(false, false); 415 ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE);
411 fm->set_instance_descriptors(*function_map_descriptors); 416 fm->set_instance_descriptors(*function_map_descriptors);
417 fm->set_function_with_prototype(true);
418
419 // Functions with this map will not have a 'prototype' property, and
420 // can not be used as constructors.
421 fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
422 global_context()->set_function_without_prototype_map(*fm);
423 function_map_descriptors =
424 ComputeFunctionInstanceDescriptor(DONT_ADD_PROTOTYPE);
425 fm->set_instance_descriptors(*function_map_descriptors);
426 fm->set_function_with_prototype(false);
412 427
413 // Allocate the function map first and then patch the prototype later 428 // Allocate the function map first and then patch the prototype later
414 fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); 429 fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
415 global_context()->set_function_map(*fm); 430 global_context()->set_function_map(*fm);
416 function_map_descriptors = ComputeFunctionInstanceDescriptor(true); 431 function_map_descriptors =
432 ComputeFunctionInstanceDescriptor(ADD_READONLY_PROTOTYPE);
417 fm->set_instance_descriptors(*function_map_descriptors); 433 fm->set_instance_descriptors(*function_map_descriptors);
434 fm->set_function_with_prototype(true);
418 435
419 Handle<String> object_name = Handle<String>(Heap::Object_symbol()); 436 Handle<String> object_name = Handle<String>(Heap::Object_symbol());
420 437
421 { // --- O b j e c t --- 438 { // --- O b j e c t ---
422 Handle<JSFunction> object_fun = 439 Handle<JSFunction> object_fun =
423 Factory::NewFunction(object_name, Factory::null_value()); 440 Factory::NewFunction(object_name, Factory::null_value());
424 Handle<Map> object_function_map = 441 Handle<Map> object_function_map =
425 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 442 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
426 object_fun->set_initial_map(*object_function_map); 443 object_fun->set_initial_map(*object_function_map);
427 object_function_map->set_constructor(*object_fun); 444 object_function_map->set_constructor(*object_fun);
(...skipping 23 matching lines...) Expand all
451 Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}")); 468 Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
452 Handle<Script> script = Factory::NewScript(source); 469 Handle<Script> script = Factory::NewScript(source);
453 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); 470 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
454 empty_function->shared()->set_script(*script); 471 empty_function->shared()->set_script(*script);
455 empty_function->shared()->set_start_position(0); 472 empty_function->shared()->set_start_position(0);
456 empty_function->shared()->set_end_position(source->length()); 473 empty_function->shared()->set_end_position(source->length());
457 empty_function->shared()->DontAdaptArguments(); 474 empty_function->shared()->DontAdaptArguments();
458 global_context()->function_map()->set_prototype(*empty_function); 475 global_context()->function_map()->set_prototype(*empty_function);
459 global_context()->function_instance_map()->set_prototype(*empty_function); 476 global_context()->function_instance_map()->set_prototype(*empty_function);
460 477
478 // Allocate a distinct prototype for this function map, so it will not add
Mads Ager (chromium) 2010/04/28 10:40:04 Make the comment a bit more explicit? How about:
dgozman 2010/04/28 11:16:59 Done.
479 // 'prototype' property in the proto chain.
480 global_context()->function_without_prototype_map()->set_prototype(
481 *Factory::NewJSObject(Top::object_function(), TENURED));
482
461 // Allocate the function map first and then patch the prototype later 483 // Allocate the function map first and then patch the prototype later
462 Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm); 484 Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
463 empty_fm->set_instance_descriptors(*function_map_descriptors); 485 empty_fm->set_instance_descriptors(*function_map_descriptors);
464 empty_fm->set_prototype(global_context()->object_function()->prototype()); 486 empty_fm->set_prototype(global_context()->object_function()->prototype());
465 empty_function->set_map(*empty_fm); 487 empty_function->set_map(*empty_fm);
466 return empty_function; 488 return empty_function;
467 } 489 }
468 490
469 491
470 void Genesis::CreateRoots() { 492 void Genesis::CreateRoots() {
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 // Install Function.prototype.call and apply. 1230 // Install Function.prototype.call and apply.
1209 { Handle<String> key = Factory::function_class_symbol(); 1231 { Handle<String> key = Factory::function_class_symbol();
1210 Handle<JSFunction> function = 1232 Handle<JSFunction> function =
1211 Handle<JSFunction>::cast(GetProperty(Top::global(), key)); 1233 Handle<JSFunction>::cast(GetProperty(Top::global(), key));
1212 Handle<JSObject> proto = 1234 Handle<JSObject> proto =
1213 Handle<JSObject>(JSObject::cast(function->instance_prototype())); 1235 Handle<JSObject>(JSObject::cast(function->instance_prototype()));
1214 1236
1215 // Install the call and the apply functions. 1237 // Install the call and the apply functions.
1216 Handle<JSFunction> call = 1238 Handle<JSFunction> call =
1217 InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize, 1239 InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize,
1218 Factory::NewJSObject(Top::object_function(), TENURED), 1240 Handle<JSObject>::null(),
1219 Builtins::FunctionCall, 1241 Builtins::FunctionCall,
1220 false); 1242 false);
1221 Handle<JSFunction> apply = 1243 Handle<JSFunction> apply =
1222 InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize, 1244 InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
1223 Factory::NewJSObject(Top::object_function(), TENURED), 1245 Handle<JSObject>::null(),
1224 Builtins::FunctionApply, 1246 Builtins::FunctionApply,
1225 false); 1247 false);
1226 1248
1227 // Make sure that Function.prototype.call appears to be compiled. 1249 // Make sure that Function.prototype.call appears to be compiled.
1228 // The code will never be called, but inline caching for call will 1250 // The code will never be called, but inline caching for call will
1229 // only work if it appears to be compiled. 1251 // only work if it appears to be compiled.
1230 call->shared()->DontAdaptArguments(); 1252 call->shared()->DontAdaptArguments();
1231 ASSERT(call->is_compiled()); 1253 ASSERT(call->is_compiled());
1232 1254
1233 // Set the expected parameters for apply to 2; required by builtin. 1255 // Set the expected parameters for apply to 2; required by builtin.
1234 apply->shared()->set_formal_parameter_count(2); 1256 apply->shared()->set_formal_parameter_count(2);
1235 1257
1236 // Set the lengths for the functions to satisfy ECMA-262. 1258 // Set the lengths for the functions to satisfy ECMA-262.
1237 call->shared()->set_length(1); 1259 call->shared()->set_length(1);
1238 apply->shared()->set_length(2); 1260 apply->shared()->set_length(2);
1261
1262 // Install the call, apply, toString and constructor properties
1263 // for the functions without prototype.
1264 Handle<JSObject> wp_proto = Handle<JSObject>(
1265 JSObject::cast(Top::function_without_prototype_map()->prototype()));
1266
1267 Handle<String> call_symbol = Factory::LookupAsciiSymbol("call");
1268 SetProperty(wp_proto, call_symbol, call, DONT_ENUM);
1269
1270 Handle<String> apply_symbol = Factory::LookupAsciiSymbol("apply");
1271 SetProperty(wp_proto, apply_symbol, apply, DONT_ENUM);
1272
1273 Handle<Object> to_string = GetProperty(proto, "toString");
1274 Handle<String> to_string_symbol = Factory::LookupAsciiSymbol("toString");
1275 SetProperty(wp_proto, to_string_symbol, to_string, DONT_ENUM);
1276
1277 SetProperty(wp_proto, Factory::constructor_symbol(), function, DONT_ENUM);
1239 } 1278 }
1240 1279
1241 // Create a constructor for RegExp results (a variant of Array that 1280 // Create a constructor for RegExp results (a variant of Array that
1242 // predefines the two properties index and match). 1281 // predefines the two properties index and match).
1243 { 1282 {
1244 // RegExpResult initial map. 1283 // RegExpResult initial map.
1245 1284
1246 // Find global.Array.prototype to inherit from. 1285 // Find global.Array.prototype to inherit from.
1247 Handle<JSFunction> array_constructor(global_context()->array_function()); 1286 Handle<JSFunction> array_constructor(global_context()->array_function());
1248 Handle<JSObject> array_prototype( 1287 Handle<JSObject> array_prototype(
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 to->set_map(*new_to_map); 1687 to->set_map(*new_to_map);
1649 } 1688 }
1650 1689
1651 1690
1652 void Genesis::MakeFunctionInstancePrototypeWritable() { 1691 void Genesis::MakeFunctionInstancePrototypeWritable() {
1653 // Make a new function map so all future functions 1692 // Make a new function map so all future functions
1654 // will have settable and enumerable prototype properties. 1693 // will have settable and enumerable prototype properties.
1655 HandleScope scope; 1694 HandleScope scope;
1656 1695
1657 Handle<DescriptorArray> function_map_descriptors = 1696 Handle<DescriptorArray> function_map_descriptors =
1658 ComputeFunctionInstanceDescriptor(false); 1697 ComputeFunctionInstanceDescriptor(ADD_WRITEABLE_PROTOTYPE);
1659 Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map()); 1698 Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
1660 fm->set_instance_descriptors(*function_map_descriptors); 1699 fm->set_instance_descriptors(*function_map_descriptors);
1700 fm->set_function_with_prototype(true);
1661 Top::context()->global_context()->set_function_map(*fm); 1701 Top::context()->global_context()->set_function_map(*fm);
1662 } 1702 }
1663 1703
1664 1704
1665 Genesis::Genesis(Handle<Object> global_object, 1705 Genesis::Genesis(Handle<Object> global_object,
1666 v8::Handle<v8::ObjectTemplate> global_template, 1706 v8::Handle<v8::ObjectTemplate> global_template,
1667 v8::ExtensionConfiguration* extensions) { 1707 v8::ExtensionConfiguration* extensions) {
1668 result_ = Handle<Context>::null(); 1708 result_ = Handle<Context>::null();
1669 // If V8 isn't running and cannot be initialized, just return. 1709 // If V8 isn't running and cannot be initialized, just return.
1670 if (!V8::IsRunning() && !V8::Initialize(NULL)) return; 1710 if (!V8::IsRunning() && !V8::Initialize(NULL)) return;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1756 } 1796 }
1757 1797
1758 1798
1759 // Restore statics that are thread local. 1799 // Restore statics that are thread local.
1760 char* BootstrapperActive::RestoreState(char* from) { 1800 char* BootstrapperActive::RestoreState(char* from) {
1761 nesting_ = *reinterpret_cast<int*>(from); 1801 nesting_ = *reinterpret_cast<int*>(from);
1762 return from + sizeof(nesting_); 1802 return from + sizeof(nesting_);
1763 } 1803 }
1764 1804
1765 } } // namespace v8::internal 1805 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/contexts.h » ('j') | test/mjsunit/function-without-prototype.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698