mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-31 03:34:08 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			269 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Copyright 2017 the V8 project authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| // Flags: --allow-natives-syntax --opt --no-always-opt
 | |
| 
 | |
| var global = this;
 | |
| 
 | |
| // TODO(ishell): update the test once const->mutable migration does not
 | |
| // create a new map.
 | |
| var IS_INPLACE_MAP_MODIFICATION_SUPPORTED = false;
 | |
| 
 | |
| var unique_id = 0;
 | |
| // Creates a function with unique SharedFunctionInfo to ensure the feedback
 | |
| // vector is unique for each test case.
 | |
| function MakeFunctionWithUniqueSFI(...args) {
 | |
|   assertTrue(args.length > 0);
 | |
|   var body = `/* Unique comment: ${unique_id++} */ ` + args.pop();
 | |
|   return new Function(...args, body);
 | |
| }
 | |
| 
 | |
| 
 | |
| //
 | |
| // Load constant field from constant object directly.
 | |
| //
 | |
| function TestLoadFromConstantFieldOfAConstantObject(the_value, other_value) {
 | |
|   function A(v) { this.v = v; }
 | |
|   function O() { this.a = new A(the_value); }
 | |
|   var the_object = new O();
 | |
| 
 | |
|   // Ensure that {the_object.a}'s map is not stable to complicate compiler's
 | |
|   // life.
 | |
|   new A(the_value).blah = 0;
 | |
| 
 | |
|   // Ensure that constant tracking is enabled for {contant_object}.
 | |
|   delete global.constant_object;
 | |
|   global.constant_object = the_object;
 | |
|   assertEquals(the_object, constant_object);
 | |
| 
 | |
|   assertTrue(%HasFastProperties(the_object));
 | |
| 
 | |
|   // {constant_object} is known to the compiler via global property cell
 | |
|   // tracking.
 | |
|   var load = MakeFunctionWithUniqueSFI("return constant_object.a.v;");
 | |
|   load();
 | |
|   load();
 | |
|   %OptimizeFunctionOnNextCall(load);
 | |
|   assertEquals(the_value, load());
 | |
|   assertOptimized(load);
 | |
|   if (IS_INPLACE_MAP_MODIFICATION_SUPPORTED) {
 | |
|     var a = new A(other_value);
 | |
|     assertTrue(%HaveSameMap(a, the_object.a));
 | |
|     // Make constant field mutable by assigning another value
 | |
|     // to some other instance of A.
 | |
|     new A(the_value).v = other_value;
 | |
|     assertTrue(%HaveSameMap(a, new A(the_value)));
 | |
|     assertTrue(%HaveSameMap(a, the_object.a));
 | |
|     assertUnoptimized(load);
 | |
|     assertEquals(the_value, load());
 | |
|   } else {
 | |
|     var a = new A(other_value);
 | |
|     assertTrue(%HaveSameMap(a, the_object.a));
 | |
|     // Make constant field mutable by assigning another value
 | |
|     // to some other instance of A.
 | |
|     new A(the_value).v = other_value;
 | |
|     assertOptimized(load);
 | |
|     assertTrue(!%HaveSameMap(a, new A(the_value)));
 | |
| 
 | |
|     assertTrue(%HaveSameMap(a, the_object.a));
 | |
|     // Ensure the {the_object.a} migrated to an up-to date version of a map
 | |
|     // by loading a property through IC.
 | |
|     assertEquals(the_value, the_object.a.v);
 | |
|     assertTrue(!%HaveSameMap(a, the_object.a));
 | |
|     assertOptimized(load);
 | |
| 
 | |
|     // Now attempt to call load should deoptimize because of failed map check.
 | |
|     assertEquals(the_value, load());
 | |
|   }
 | |
|   assertUnoptimized(load);
 | |
|   assertEquals(the_value, load());
 | |
| }
 | |
| 
 | |
| // Test constant tracking with Smi value.
 | |
| (function() {
 | |
|   var the_value = 42;
 | |
|   var other_value = 153;
 | |
|   TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with double value.
 | |
| (function() {
 | |
|   var the_value = 0.9;
 | |
|   var other_value = 0.42;
 | |
|   TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with function value.
 | |
| (function() {
 | |
|   var the_value = function V() {};
 | |
|   var other_value = function W() {};
 | |
|   TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with heap object value.
 | |
| (function() {
 | |
|   function V() {}
 | |
|   var the_value = new V();
 | |
|   var other_value = new V();
 | |
|   TestLoadFromConstantFieldOfAConstantObject(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| 
 | |
| //
 | |
| // Load constant field from a prototype.
 | |
| //
 | |
| function TestLoadFromConstantFieldOfAPrototype(the_value, other_value) {
 | |
|   function Proto() { this.v = the_value; }
 | |
|   var the_prototype = new Proto();
 | |
| 
 | |
|   function O() {}
 | |
|   O.prototype = the_prototype;
 | |
|   var the_object = new O();
 | |
| 
 | |
|   // Ensure O.prototype is in fast mode by loading from its field.
 | |
|   function warmup() { return new O().v; }
 | |
|   warmup(); warmup(); warmup();
 | |
|   assertTrue(%HasFastProperties(O.prototype));
 | |
| 
 | |
|   // The parameter object is not constant but all the values have the same
 | |
|   // map and therefore the compiler knows the prototype object and can
 | |
|   // optimize load of "v".
 | |
|   var load = MakeFunctionWithUniqueSFI("o", "return o.v;");
 | |
|   load(new O());
 | |
|   load(new O());
 | |
|   %OptimizeFunctionOnNextCall(load);
 | |
|   assertEquals(the_value, load(new O()));
 | |
|   assertOptimized(load);
 | |
|   if (IS_INPLACE_MAP_MODIFICATION_SUPPORTED) {
 | |
|     // Invalidation of mutability should trigger deoptimization with a
 | |
|     // "field-owner" reason.
 | |
|     the_prototype.v = other_value;
 | |
|   } else {
 | |
|     // Invalidation of mutability should trigger deoptimization with a
 | |
|     // "prototype-check" (stability) reason.
 | |
|     the_prototype.v = other_value;
 | |
|   }
 | |
|   assertUnoptimized(load);
 | |
| }
 | |
| 
 | |
| // Test constant tracking with Smi value.
 | |
| (function() {
 | |
|   var the_value = 42;
 | |
|   var other_value = 153;
 | |
|   TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with double value.
 | |
| (function() {
 | |
|   var the_value = 0.9;
 | |
|   var other_value = 0.42;
 | |
|   TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with function value.
 | |
| (function() {
 | |
|   var the_value = function V() {};
 | |
|   var other_value = function W() {};
 | |
|   TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with heap object value.
 | |
| (function() {
 | |
|   function V() {}
 | |
|   var the_value = new V();
 | |
|   var other_value = new V();
 | |
|   TestLoadFromConstantFieldOfAPrototype(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| 
 | |
| //
 | |
| // Store to constant field of a constant object.
 | |
| //
 | |
| function TestStoreToConstantFieldOfConstantObject(the_value, other_value) {
 | |
|   function A(v) { this.v = v; }
 | |
|   function O() { this.a = new A(the_value); }
 | |
|   var the_object = new O();
 | |
| 
 | |
|   // Ensure that {the_object.a}'s map is not stable to complicate compiler's
 | |
|   // life.
 | |
|   new A(the_value).blah = 0;
 | |
| 
 | |
|   // Ensure that constant tracking is enabled for {contant_object}.
 | |
|   delete global.constant_object;
 | |
|   global.constant_object = the_object;
 | |
|   assertEquals(the_object, constant_object);
 | |
| 
 | |
|   assertTrue(%HasFastProperties(the_object));
 | |
| 
 | |
|   // {constant_object} is known to the compiler via global property cell
 | |
|   // tracking.
 | |
|   var store = MakeFunctionWithUniqueSFI("v", "constant_object.a.v = v;");
 | |
|   store(the_value);
 | |
|   store(the_value);
 | |
|   %OptimizeFunctionOnNextCall(store);
 | |
|   store(the_value);
 | |
|   assertEquals(the_value, constant_object.a.v);
 | |
|   assertOptimized(store);
 | |
|   // Storing of the same value does not deoptimize.
 | |
|   store(the_value);
 | |
|   assertEquals(the_value, constant_object.a.v);
 | |
|   assertOptimized(store);
 | |
| 
 | |
|   if (IS_INPLACE_MAP_MODIFICATION_SUPPORTED) {
 | |
|     var a = new A(other_value);
 | |
| 
 | |
|     if (typeof the_value == "function" || typeof the_value == "object") {
 | |
|       // For heap object fields "field-owner" dependency is installed for
 | |
|       // any access of the field, therefore making constant field mutable by
 | |
|       // assigning other value to some other instance of A should already
 | |
|       // trigger deoptimization.
 | |
|       assertTrue(%HaveSameMap(a, the_object.a));
 | |
|       new A(the_value).v = other_value;
 | |
|       assertTrue(%HaveSameMap(a, new A(the_value)));
 | |
|       assertTrue(%HaveSameMap(a, the_object.a));
 | |
|       assertUnoptimized(store);
 | |
|     } else {
 | |
|       assertOptimized(store);
 | |
|     }
 | |
|     // Storing other value deoptimizes because of failed value check.
 | |
|     store(other_value);
 | |
|     assertUnoptimized(store);
 | |
|     assertEquals(other_value, constant_object.a.v);
 | |
|   } else {
 | |
|     // Storing other value deoptimizes because of failed value check.
 | |
|     store(other_value);
 | |
|     assertUnoptimized(store);
 | |
|     assertEquals(other_value, constant_object.a.v);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Test constant tracking with Smi values.
 | |
| (function() {
 | |
|   var the_value = 42;
 | |
|   var other_value = 153;
 | |
|   TestStoreToConstantFieldOfConstantObject(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with double values.
 | |
| (function() {
 | |
|   var the_value = 0.9;
 | |
|   var other_value = 0.42
 | |
|   TestStoreToConstantFieldOfConstantObject(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with function values.
 | |
| (function() {
 | |
|   var the_value = function V() {};
 | |
|   var other_value = function W() {};
 | |
|   TestStoreToConstantFieldOfConstantObject(the_value, other_value);
 | |
| })();
 | |
| 
 | |
| // Test constant tracking with heap object values.
 | |
| (function() {
 | |
|   function V() {}
 | |
|   var the_value = new V();
 | |
|   var other_value = new V();
 | |
|   TestStoreToConstantFieldOfConstantObject(the_value, other_value);
 | |
| })();
 |