 Chromium Code Reviews
 Chromium Code Reviews Issue 1722003:
  Added ability to remove prototype from function. In this case, [[Construct]] ...  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
    
  
    Issue 1722003:
  Added ability to remove prototype from function. In this case, [[Construct]] ...  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/| OLD | NEW | 
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 | 
| OLD | NEW |