OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 "bootstrapper.h" | 5 #include "bootstrapper.h" |
6 | 6 |
7 #include "accessors.h" | 7 #include "accessors.h" |
8 #include "isolate-inl.h" | 8 #include "isolate-inl.h" |
9 #include "natives.h" | 9 #include "natives.h" |
10 #include "snapshot.h" | 10 #include "snapshot.h" |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 Handle<Context> result() { return result_; } | 160 Handle<Context> result() { return result_; } |
161 | 161 |
162 private: | 162 private: |
163 Handle<Context> native_context() { return native_context_; } | 163 Handle<Context> native_context() { return native_context_; } |
164 | 164 |
165 // Creates some basic objects. Used for creating a context from scratch. | 165 // Creates some basic objects. Used for creating a context from scratch. |
166 void CreateRoots(); | 166 void CreateRoots(); |
167 // Creates the empty function. Used for creating a context from scratch. | 167 // Creates the empty function. Used for creating a context from scratch. |
168 Handle<JSFunction> CreateEmptyFunction(Isolate* isolate); | 168 Handle<JSFunction> CreateEmptyFunction(Isolate* isolate); |
169 // Creates the ThrowTypeError function. ECMA 5th Ed. 13.2.3 | 169 // Creates the ThrowTypeError function. ECMA 5th Ed. 13.2.3 |
170 Handle<JSFunction> GetThrowTypeErrorFunction(); | 170 Handle<JSFunction> GetStrictPoisonFunction(); |
| 171 // Poison for sloppy generator function arguments/callee. |
| 172 Handle<JSFunction> GetGeneratorPoisonFunction(); |
171 | 173 |
172 void CreateStrictModeFunctionMaps(Handle<JSFunction> empty); | 174 void CreateStrictModeFunctionMaps(Handle<JSFunction> empty); |
173 | 175 |
174 // Make the "arguments" and "caller" properties throw a TypeError on access. | 176 // Make the "arguments" and "caller" properties throw a TypeError on access. |
175 void PoisonArgumentsAndCaller(Handle<Map> map); | 177 void PoisonArgumentsAndCaller(Handle<Map> map); |
176 | 178 |
177 // Creates the global objects using the global and the template passed in | 179 // Creates the global objects using the global and the template passed in |
178 // through the API. We call this regardless of whether we are building a | 180 // through the API. We call this regardless of whether we are building a |
179 // context from scratch or using a deserialized one from the partial snapshot | 181 // context from scratch or using a deserialized one from the partial snapshot |
180 // but in the latter case we don't use the objects it produces directly, as | 182 // but in the latter case we don't use the objects it produces directly, as |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 Isolate* isolate_; | 297 Isolate* isolate_; |
296 Handle<Context> result_; | 298 Handle<Context> result_; |
297 Handle<Context> native_context_; | 299 Handle<Context> native_context_; |
298 | 300 |
299 // Function maps. Function maps are created initially with a read only | 301 // Function maps. Function maps are created initially with a read only |
300 // prototype for the processing of JS builtins. Later the function maps are | 302 // prototype for the processing of JS builtins. Later the function maps are |
301 // replaced in order to make prototype writable. These are the final, writable | 303 // replaced in order to make prototype writable. These are the final, writable |
302 // prototype, maps. | 304 // prototype, maps. |
303 Handle<Map> sloppy_function_map_writable_prototype_; | 305 Handle<Map> sloppy_function_map_writable_prototype_; |
304 Handle<Map> strict_function_map_writable_prototype_; | 306 Handle<Map> strict_function_map_writable_prototype_; |
305 Handle<JSFunction> throw_type_error_function; | 307 Handle<JSFunction> strict_poison_function; |
| 308 Handle<JSFunction> generator_poison_function; |
306 | 309 |
307 BootstrapperActive active_; | 310 BootstrapperActive active_; |
308 friend class Bootstrapper; | 311 friend class Bootstrapper; |
309 }; | 312 }; |
310 | 313 |
311 | 314 |
312 void Bootstrapper::Iterate(ObjectVisitor* v) { | 315 void Bootstrapper::Iterate(ObjectVisitor* v) { |
313 extensions_cache_.Iterate(v); | 316 extensions_cache_.Iterate(v); |
314 v->Synchronize(VisitorSynchronization::kExtensions); | 317 v->Synchronize(VisitorSynchronization::kExtensions); |
315 } | 318 } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 Handle<AccessorInfo> prototype = | 565 Handle<AccessorInfo> prototype = |
563 Accessors::FunctionPrototypeInfo(isolate(), attribs); | 566 Accessors::FunctionPrototypeInfo(isolate(), attribs); |
564 CallbacksDescriptor d(Handle<Name>(Name::cast(prototype->name())), | 567 CallbacksDescriptor d(Handle<Name>(Name::cast(prototype->name())), |
565 prototype, attribs); | 568 prototype, attribs); |
566 map->AppendDescriptor(&d); | 569 map->AppendDescriptor(&d); |
567 } | 570 } |
568 } | 571 } |
569 | 572 |
570 | 573 |
571 // ECMAScript 5th Edition, 13.2.3 | 574 // ECMAScript 5th Edition, 13.2.3 |
572 Handle<JSFunction> Genesis::GetThrowTypeErrorFunction() { | 575 Handle<JSFunction> Genesis::GetStrictPoisonFunction() { |
573 if (throw_type_error_function.is_null()) { | 576 if (strict_poison_function.is_null()) { |
574 Handle<String> name = factory()->InternalizeOneByteString( | 577 Handle<String> name = factory()->InternalizeOneByteString( |
575 STATIC_ASCII_VECTOR("ThrowTypeError")); | 578 STATIC_ASCII_VECTOR("ThrowTypeError")); |
576 Handle<Code> code(isolate()->builtins()->builtin( | 579 Handle<Code> code(isolate()->builtins()->builtin( |
577 Builtins::kStrictModePoisonPill)); | 580 Builtins::kStrictModePoisonPill)); |
578 throw_type_error_function = factory()->NewFunction(name, code); | 581 strict_poison_function = factory()->NewFunction(name, code); |
579 throw_type_error_function->set_map(native_context()->sloppy_function_map()); | 582 strict_poison_function->set_map(native_context()->sloppy_function_map()); |
580 throw_type_error_function->shared()->DontAdaptArguments(); | 583 strict_poison_function->shared()->DontAdaptArguments(); |
581 | 584 |
582 JSObject::PreventExtensions(throw_type_error_function).Assert(); | 585 JSObject::PreventExtensions(strict_poison_function).Assert(); |
583 } | 586 } |
584 return throw_type_error_function; | 587 return strict_poison_function; |
585 } | 588 } |
586 | 589 |
587 | 590 |
| 591 Handle<JSFunction> Genesis::GetGeneratorPoisonFunction() { |
| 592 if (generator_poison_function.is_null()) { |
| 593 Handle<String> name = factory()->InternalizeOneByteString( |
| 594 STATIC_ASCII_VECTOR("ThrowTypeError")); |
| 595 Handle<Code> code(isolate()->builtins()->builtin( |
| 596 Builtins::kGeneratorPoisonPill)); |
| 597 generator_poison_function = factory()->NewFunction(name, code); |
| 598 generator_poison_function->set_map(native_context()->sloppy_function_map()); |
| 599 generator_poison_function->shared()->DontAdaptArguments(); |
| 600 |
| 601 JSObject::PreventExtensions(generator_poison_function).Assert(); |
| 602 } |
| 603 return generator_poison_function; |
| 604 } |
| 605 |
| 606 |
588 Handle<Map> Genesis::CreateStrictFunctionMap( | 607 Handle<Map> Genesis::CreateStrictFunctionMap( |
589 PrototypePropertyMode prototype_mode, | 608 PrototypePropertyMode prototype_mode, |
590 Handle<JSFunction> empty_function) { | 609 Handle<JSFunction> empty_function) { |
591 Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); | 610 Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); |
592 SetStrictFunctionInstanceDescriptor(map, prototype_mode); | 611 SetStrictFunctionInstanceDescriptor(map, prototype_mode); |
593 map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE); | 612 map->set_function_with_prototype(prototype_mode != DONT_ADD_PROTOTYPE); |
594 map->set_prototype(*empty_function); | 613 map->set_prototype(*empty_function); |
595 return map; | 614 return map; |
596 } | 615 } |
597 | 616 |
(...skipping 28 matching lines...) Expand all Loading... |
626 Handle<String> name, | 645 Handle<String> name, |
627 Handle<JSFunction> func) { | 646 Handle<JSFunction> func) { |
628 DescriptorArray* descs = map->instance_descriptors(); | 647 DescriptorArray* descs = map->instance_descriptors(); |
629 int number = descs->SearchWithCache(*name, *map); | 648 int number = descs->SearchWithCache(*name, *map); |
630 AccessorPair* accessors = AccessorPair::cast(descs->GetValue(number)); | 649 AccessorPair* accessors = AccessorPair::cast(descs->GetValue(number)); |
631 accessors->set_getter(*func); | 650 accessors->set_getter(*func); |
632 accessors->set_setter(*func); | 651 accessors->set_setter(*func); |
633 } | 652 } |
634 | 653 |
635 | 654 |
| 655 static void ReplaceAccessors(Handle<Map> map, |
| 656 Handle<String> name, |
| 657 PropertyAttributes attributes, |
| 658 Handle<AccessorPair> accessor_pair) { |
| 659 DescriptorArray* descriptors = map->instance_descriptors(); |
| 660 int idx = descriptors->SearchWithCache(*name, *map); |
| 661 CallbacksDescriptor descriptor(name, accessor_pair, attributes); |
| 662 descriptors->Replace(idx, &descriptor); |
| 663 } |
| 664 |
| 665 |
636 void Genesis::PoisonArgumentsAndCaller(Handle<Map> map) { | 666 void Genesis::PoisonArgumentsAndCaller(Handle<Map> map) { |
637 SetAccessors(map, factory()->arguments_string(), GetThrowTypeErrorFunction()); | 667 SetAccessors(map, factory()->arguments_string(), GetStrictPoisonFunction()); |
638 SetAccessors(map, factory()->caller_string(), GetThrowTypeErrorFunction()); | 668 SetAccessors(map, factory()->caller_string(), GetStrictPoisonFunction()); |
639 } | 669 } |
640 | 670 |
641 | 671 |
642 static void AddToWeakNativeContextList(Context* context) { | 672 static void AddToWeakNativeContextList(Context* context) { |
643 ASSERT(context->IsNativeContext()); | 673 ASSERT(context->IsNativeContext()); |
644 Heap* heap = context->GetIsolate()->heap(); | 674 Heap* heap = context->GetIsolate()->heap(); |
645 #ifdef DEBUG | 675 #ifdef DEBUG |
646 { // NOLINT | 676 { // NOLINT |
647 ASSERT(context->get(Context::NEXT_CONTEXT_LINK)->IsUndefined()); | 677 ASSERT(context->get(Context::NEXT_CONTEXT_LINK)->IsUndefined()); |
648 // Check that context is not in the list yet. | 678 // Check that context is not in the list yet. |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1155 } | 1185 } |
1156 | 1186 |
1157 { // --- strict mode arguments boilerplate | 1187 { // --- strict mode arguments boilerplate |
1158 const PropertyAttributes attributes = | 1188 const PropertyAttributes attributes = |
1159 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); | 1189 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); |
1160 | 1190 |
1161 // Create the ThrowTypeError functions. | 1191 // Create the ThrowTypeError functions. |
1162 Handle<AccessorPair> callee = factory->NewAccessorPair(); | 1192 Handle<AccessorPair> callee = factory->NewAccessorPair(); |
1163 Handle<AccessorPair> caller = factory->NewAccessorPair(); | 1193 Handle<AccessorPair> caller = factory->NewAccessorPair(); |
1164 | 1194 |
1165 Handle<JSFunction> throw_function = | 1195 Handle<JSFunction> poison = GetStrictPoisonFunction(); |
1166 GetThrowTypeErrorFunction(); | |
1167 | 1196 |
1168 // Install the ThrowTypeError functions. | 1197 // Install the ThrowTypeError functions. |
1169 callee->set_getter(*throw_function); | 1198 callee->set_getter(*poison); |
1170 callee->set_setter(*throw_function); | 1199 callee->set_setter(*poison); |
1171 caller->set_getter(*throw_function); | 1200 caller->set_getter(*poison); |
1172 caller->set_setter(*throw_function); | 1201 caller->set_setter(*poison); |
1173 | 1202 |
1174 // Create the map. Allocate one in-object field for length. | 1203 // Create the map. Allocate one in-object field for length. |
1175 Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, | 1204 Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, |
1176 Heap::kStrictArgumentsObjectSize); | 1205 Heap::kStrictArgumentsObjectSize); |
1177 // Create the descriptor array for the arguments object. | 1206 // Create the descriptor array for the arguments object. |
1178 Map::EnsureDescriptorSlack(map, 3); | 1207 Map::EnsureDescriptorSlack(map, 3); |
1179 | 1208 |
1180 { // length | 1209 { // length |
1181 FieldDescriptor d( | 1210 FieldDescriptor d( |
1182 factory->length_string(), 0, DONT_ENUM, Representation::Tagged()); | 1211 factory->length_string(), 0, DONT_ENUM, Representation::Tagged()); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 JS_FUNCTION_TYPE, JSFunction::kHeaderSize, | 1388 JS_FUNCTION_TYPE, JSFunction::kHeaderSize, |
1360 generator_object_prototype, Builtins::kIllegal, | 1389 generator_object_prototype, Builtins::kIllegal, |
1361 false, false); | 1390 false, false); |
1362 InstallFunction(builtins, "GeneratorFunction", | 1391 InstallFunction(builtins, "GeneratorFunction", |
1363 JS_FUNCTION_TYPE, JSFunction::kSize, | 1392 JS_FUNCTION_TYPE, JSFunction::kSize, |
1364 generator_function_prototype, Builtins::kIllegal, | 1393 generator_function_prototype, Builtins::kIllegal, |
1365 false, false); | 1394 false, false); |
1366 | 1395 |
1367 // Create maps for generator functions and their prototypes. Store those | 1396 // Create maps for generator functions and their prototypes. Store those |
1368 // maps in the native context. | 1397 // maps in the native context. |
1369 Handle<Map> function_map(native_context()->sloppy_function_map()); | 1398 Handle<Map> sloppy_function_map(native_context()->sloppy_function_map()); |
1370 Handle<Map> generator_function_map = Map::Copy(function_map); | 1399 Handle<Map> generator_function_map = Map::Copy(sloppy_function_map); |
1371 generator_function_map->set_prototype(*generator_function_prototype); | 1400 generator_function_map->set_prototype(*generator_function_prototype); |
1372 native_context()->set_sloppy_generator_function_map( | 1401 native_context()->set_sloppy_generator_function_map( |
1373 *generator_function_map); | 1402 *generator_function_map); |
1374 | 1403 |
1375 Handle<Map> strict_mode_function_map( | 1404 // The "arguments" and "caller" instance properties aren't specified, so |
1376 native_context()->strict_function_map()); | 1405 // technically we could leave them out. They make even less sense for |
1377 Handle<Map> strict_mode_generator_function_map = | 1406 // generators than for functions. Still, the same argument that it makes |
1378 Map::Copy(strict_mode_function_map); | 1407 // sense to keep them around but poisoned in strict mode applies to |
1379 strict_mode_generator_function_map->set_prototype( | 1408 // generators as well. With poisoned accessors, naive callers can still |
1380 *generator_function_prototype); | 1409 // iterate over the properties without accessing them. |
| 1410 // |
| 1411 // We can't use PoisonArgumentsAndCaller because that mutates accessor pairs |
| 1412 // in place, and the initial state of the generator function map shares the |
| 1413 // accessor pair with sloppy functions. Also the error message should be |
| 1414 // different. Also unhappily, we can't use the API accessors to implement |
| 1415 // poisoning, because API accessors present themselves as data properties, |
| 1416 // not accessor properties, and so getOwnPropertyDescriptor raises an |
| 1417 // exception as it tries to get the values. Sadness. |
| 1418 Handle<AccessorPair> poison_pair(factory()->NewAccessorPair()); |
| 1419 PropertyAttributes rw_attribs = |
| 1420 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); |
| 1421 poison_pair->set_getter(*GetGeneratorPoisonFunction()); |
| 1422 poison_pair->set_setter(*GetGeneratorPoisonFunction()); |
| 1423 ReplaceAccessors(generator_function_map, factory()->arguments_string(), |
| 1424 rw_attribs, poison_pair); |
| 1425 ReplaceAccessors(generator_function_map, factory()->caller_string(), |
| 1426 rw_attribs, poison_pair); |
| 1427 |
| 1428 Handle<Map> strict_function_map(native_context()->strict_function_map()); |
| 1429 Handle<Map> strict_generator_function_map = Map::Copy(strict_function_map); |
| 1430 // "arguments" and "caller" already poisoned. |
| 1431 strict_generator_function_map->set_prototype(*generator_function_prototype); |
1381 native_context()->set_strict_generator_function_map( | 1432 native_context()->set_strict_generator_function_map( |
1382 *strict_mode_generator_function_map); | 1433 *strict_generator_function_map); |
1383 | 1434 |
1384 Handle<JSFunction> object_function(native_context()->object_function()); | 1435 Handle<JSFunction> object_function(native_context()->object_function()); |
1385 Handle<Map> generator_object_prototype_map = Map::Create( | 1436 Handle<Map> generator_object_prototype_map = Map::Create( |
1386 object_function, 0); | 1437 object_function, 0); |
1387 generator_object_prototype_map->set_prototype( | 1438 generator_object_prototype_map->set_prototype( |
1388 *generator_object_prototype); | 1439 *generator_object_prototype); |
1389 native_context()->set_generator_object_prototype_map( | 1440 native_context()->set_generator_object_prototype_map( |
1390 *generator_object_prototype_map); | 1441 *generator_object_prototype_map); |
1391 } | 1442 } |
1392 | 1443 |
(...skipping 1305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2698 return from + sizeof(NestingCounterType); | 2749 return from + sizeof(NestingCounterType); |
2699 } | 2750 } |
2700 | 2751 |
2701 | 2752 |
2702 // Called when the top-level V8 mutex is destroyed. | 2753 // Called when the top-level V8 mutex is destroyed. |
2703 void Bootstrapper::FreeThreadResources() { | 2754 void Bootstrapper::FreeThreadResources() { |
2704 ASSERT(!IsActive()); | 2755 ASSERT(!IsActive()); |
2705 } | 2756 } |
2706 | 2757 |
2707 } } // namespace v8::internal | 2758 } } // namespace v8::internal |
OLD | NEW |