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

Side by Side Diff: src/bootstrapper.cc

Issue 270133003: Poison .arguments and .caller for generator functions (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address nits, add tests Created 6 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/builtins.h » ('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 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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/builtins.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698