mirror of
				https://github.com/tc39/test262.git
				synced 2025-11-04 13:44:29 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			366 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			366 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// Copyright 2018 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
 | 
						|
 | 
						|
 | 
						|
// Test CloneFastJSArray inserted by JSCallReducer for Array.prototype.slice.
 | 
						|
// CloneFastJSArray produces COW arrays if the original array is COW.
 | 
						|
 | 
						|
// Trigger JSCallReducer on slice() and slice(0)
 | 
						|
(function() {
 | 
						|
  const arr = [1,2,3,4,5];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return arr.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  function slice0() {
 | 
						|
    return arr.slice(0);
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(arr, slice());
 | 
						|
  assertFalse(arr === slice());
 | 
						|
  assertEquals(slice(), slice0());
 | 
						|
  assertEquals(slice0(), slice());
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice0);
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
 | 
						|
  assertEquals(slice(), slice0());
 | 
						|
  assertOptimized(slice); assertOptimized(slice0);
 | 
						|
})();
 | 
						|
 | 
						|
// This will cause deopt of slice by a CheckMap installed by
 | 
						|
// JSNativeContextSpecialization::ReduceNamedAccess
 | 
						|
(function() {
 | 
						|
  const arr = [1,2,3,4,5];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return arr.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(arr, slice());
 | 
						|
  assertEquals(slice(), arr);
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  slice();
 | 
						|
 | 
						|
  // Trigger deopt here
 | 
						|
  arr.push(7.2);
 | 
						|
  assertEquals(slice()[5], 7.2);
 | 
						|
})();
 | 
						|
 | 
						|
// There should not be a deopt cycle.
 | 
						|
(function() {
 | 
						|
  const arr = [1,2,3,4,5];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return arr.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(arr, slice());
 | 
						|
  assertEquals(slice(), arr);
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  // Trigger opt
 | 
						|
  assertEquals(slice(), arr);
 | 
						|
 | 
						|
  // Trigger deopt by CheckMap from JSNativeContextSpecialization
 | 
						|
  arr.push(7.2);
 | 
						|
  slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  // Trigger opt again
 | 
						|
  slice();
 | 
						|
 | 
						|
  // Should not deopt again
 | 
						|
  arr.push(8.2);
 | 
						|
  slice();
 | 
						|
  assertOptimized(slice);
 | 
						|
})();
 | 
						|
 | 
						|
// JSCallReducer will not reduce because the species has been modified
 | 
						|
(function() {
 | 
						|
  const array = [3,4,5];
 | 
						|
 | 
						|
  function slice(){
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  class MyArray extends Array {};
 | 
						|
  array.constructor = MyArray;
 | 
						|
 | 
						|
  slice(); slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  var narr = slice();
 | 
						|
  assertInstanceof(narr, MyArray);
 | 
						|
})();
 | 
						|
 | 
						|
(function() {
 | 
						|
  const array = [3,4,5];
 | 
						|
 | 
						|
  function slice(){
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  slice(); slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
 | 
						|
  slice();
 | 
						|
 | 
						|
  class MyArray extends Array {};
 | 
						|
  array.constructor = MyArray;
 | 
						|
  // deopt
 | 
						|
  var narr = slice();
 | 
						|
  // if not deopt, narr will be instanceof Array
 | 
						|
  assertTrue(narr instanceof MyArray);
 | 
						|
})();
 | 
						|
 | 
						|
// JSCallReducer adds check for UnreliableReceiverMaps
 | 
						|
(function() {
 | 
						|
  const arr = [1,2,3,4,5];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return arr.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  slice(); slice();
 | 
						|
  arr.foo = 6.2;
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  // JSCallReducer will add check for UnreliableReceiverMaps
 | 
						|
  slice();
 | 
						|
 | 
						|
  // Trigger deopt because of DependOnStableMaps
 | 
						|
  // installed by JSNativeContextSpecialization,
 | 
						|
  // but not the check installed by ReduceArrayPrototypeSlice itself
 | 
						|
  arr.bar = 7.2;
 | 
						|
 | 
						|
  let narr = slice();
 | 
						|
  assertEquals(arr, narr);
 | 
						|
  assertEquals(narr.foo, undefined);
 | 
						|
  assertEquals(narr.bar, undefined);
 | 
						|
})();
 | 
						|
 | 
						|
// Multiple maps
 | 
						|
(function() {
 | 
						|
  const iarr = [1,2,3];
 | 
						|
  const darr = [2.1, 3.3, 0.2];
 | 
						|
 | 
						|
  function slice(arr) {
 | 
						|
    return arr.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  slice(iarr); slice(darr);
 | 
						|
  slice(iarr); slice(darr);
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  // The optimization works for both maps
 | 
						|
  assertEquals(iarr, slice(iarr));
 | 
						|
  assertEquals(darr, slice(darr));
 | 
						|
  assertOptimized(slice);
 | 
						|
})();
 | 
						|
 | 
						|
// Tests for the branch of CanInlineArrayIteratingBuiltin
 | 
						|
 | 
						|
// JSCallReducer will not reduce to CloneFastJSArray
 | 
						|
// if array's prototype is not JS_ARRAY_TYPE
 | 
						|
(function () {
 | 
						|
  class MyArray extends Array {
 | 
						|
    constructor() {
 | 
						|
      super();
 | 
						|
      this[6]= 6;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  let array = new MyArray(3, 5, 4);
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(slice(),array);
 | 
						|
  slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  let narr = slice();
 | 
						|
  // here, slice supposes to call MyArray's constructor.
 | 
						|
  // If we optimize with CloneFastJSArray, Array's constructor is called instead.
 | 
						|
  assertEquals(narr[6], 6);
 | 
						|
  assertTrue(narr instanceof MyArray);
 | 
						|
})();
 | 
						|
 | 
						|
// JSCallReducer will not reduce to CloneFastJSArray
 | 
						|
// if array's instance type is not JS_ARRAY_TYPE.
 | 
						|
// CloneFastJSArray does not work with non JS_ARRAY_TYPE.
 | 
						|
// Check : receiver_map->instance_type() == JS_ARRAY_TYPE
 | 
						|
(function () {
 | 
						|
  var x = {"0" : 0, "2": 2} ;
 | 
						|
  x.__proto__ = Array.prototype;
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return x.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  slice(); slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  assertEquals(slice(), []);
 | 
						|
})();
 | 
						|
 | 
						|
// JSCallReducer will not reduce to CloneFastJSArray
 | 
						|
// since array is not Fast Elements Kind
 | 
						|
// Check : IsFastElementsKind(receiver_map->elements_kind())
 | 
						|
(function () {
 | 
						|
  var array = [3, 4, 5];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(slice(),array);
 | 
						|
  slice();
 | 
						|
 | 
						|
  // a sparse array switches to Dictionary Elements
 | 
						|
  array[9999] = 0;
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  var narr = slice();
 | 
						|
  assertEquals(narr, array);
 | 
						|
})();
 | 
						|
 | 
						|
(function () {
 | 
						|
  var array = [3, 4, 5];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(slice(),array);
 | 
						|
  slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  slice();
 | 
						|
 | 
						|
  // a sparse array switches to Dictionary Elements
 | 
						|
  array[9999] = 0;
 | 
						|
  // trigger deopt because map changes
 | 
						|
  assertEquals(slice(),array);
 | 
						|
})();
 | 
						|
 | 
						|
// JSCallReducer will not reduce to CloneFastJSArray
 | 
						|
// if array is used as a prototype and has unstable map
 | 
						|
(function () {
 | 
						|
  var array = [3, 5, 4];
 | 
						|
 | 
						|
  function slice(arr) {
 | 
						|
    return arr.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  // make array's map is_prototype_map()
 | 
						|
  var x = {__proto__ : array};
 | 
						|
 | 
						|
  assertEquals(slice(array),array);
 | 
						|
  slice(array);
 | 
						|
 | 
						|
  // make array's map unstable
 | 
						|
  array.push(6.3);
 | 
						|
  slice(array);
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
 | 
						|
  assertEquals(slice(array),array);
 | 
						|
})();
 | 
						|
 | 
						|
// JSCallReducer will not reduce to CloneFastJSArray
 | 
						|
// if the Array prototype got some elements.
 | 
						|
// Check: isolate->IsNoElementsProtectorIntact()
 | 
						|
(function () {
 | 
						|
  var array = [, 6, 6];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(slice(),array);
 | 
						|
  slice();
 | 
						|
 | 
						|
  array.__proto__.push(6);
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
 | 
						|
  // if we optimized, we would get [ , 6, 6]
 | 
						|
  // here, slice copies elements from both the object and the prototype
 | 
						|
  let narr = slice();
 | 
						|
  assertNotEquals(Object.getOwnPropertyDescriptor(narr,0), undefined);
 | 
						|
  assertEquals(narr, [6, 6, 6]);
 | 
						|
})();
 | 
						|
 | 
						|
(function () {
 | 
						|
  var array = [, 6, 6];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(slice(),array);
 | 
						|
  slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  slice();
 | 
						|
 | 
						|
  // Deopt
 | 
						|
  array.__proto__.push(6);
 | 
						|
  let narr = slice();
 | 
						|
  assertNotEquals(Object.getOwnPropertyDescriptor(narr, 0), undefined);
 | 
						|
  assertEquals(narr[0], 6);
 | 
						|
})();
 | 
						|
 | 
						|
// JSCallReducer will not reduce to CloneFastJSArray
 | 
						|
// if the Array prototype is not original
 | 
						|
// Check: isolate->IsAnyInitialArrayPrototype(receiver_prototype)
 | 
						|
(function () {
 | 
						|
  var array = [6, , 6];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(slice(),array);
 | 
						|
  slice();
 | 
						|
 | 
						|
  // change the prototype
 | 
						|
  array.__proto__ = [ , 6, ];
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  let narr = slice();
 | 
						|
  // if optimized, we would get [6, , 6]
 | 
						|
  assertNotEquals(Object.getOwnPropertyDescriptor(narr, 1), undefined);
 | 
						|
  assertEquals(narr, [6,6,6]);
 | 
						|
})();
 | 
						|
 | 
						|
(function () {
 | 
						|
  var array = [6, ,6];
 | 
						|
 | 
						|
  function slice() {
 | 
						|
    return array.slice();
 | 
						|
  }
 | 
						|
 | 
						|
  assertEquals(slice(),array);
 | 
						|
  slice();
 | 
						|
 | 
						|
  %OptimizeFunctionOnNextCall(slice);
 | 
						|
  slice();
 | 
						|
 | 
						|
  // change the prototype
 | 
						|
  array.__proto__ = [,6,];
 | 
						|
  // deopt because of map changed
 | 
						|
  let narr = slice();
 | 
						|
 | 
						|
  // if optimized, we would get [6, , 6]
 | 
						|
  assertNotEquals(Object.getOwnPropertyDescriptor(narr, 1), undefined);
 | 
						|
  assertEquals(narr, [6,6,6]);
 | 
						|
})();
 |