mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-31 11:44:31 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			166 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| //@ skip if $architecture == "x86"
 | |
| 
 | |
| var createBuiltin = $vm.createBuiltin;
 | |
| 
 | |
| // This is pretty bad but I need a private name.
 | |
| var putFuncToPrivateName = createBuiltin(`(function (func) { @arrayIteratorIsDone = func })`)
 | |
| putFuncToPrivateName(function (a,b) { return b; })
 | |
| 
 | |
| function createTailCallForwardingFuncWith(body, thisValue) {
 | |
|     return createBuiltin(`(function (a) {
 | |
|         "use strict";
 | |
| 
 | |
|         ${body}
 | |
| 
 | |
|         return @tailCallForwardArguments(@arrayIteratorIsDone, ${thisValue});
 | |
|     })`);
 | |
| }
 | |
| 
 | |
| var foo = createTailCallForwardingFuncWith("", "@undefined");
 | |
| 
 | |
| function baz() {
 | |
|     return foo.call(true, 7);
 | |
| }
 | |
| noInline(baz);
 | |
| 
 | |
| 
 | |
| 
 | |
| var fooNoInline = createTailCallForwardingFuncWith("", "@undefined");
 | |
| noInline(foo);
 | |
| 
 | |
| for (let i = 0; i < 100000; i++) {
 | |
|     if (baz.call() !== undefined)
 | |
|         throw new Error(i);
 | |
|     if (fooNoInline.call(undefined, 3) !== undefined)
 | |
|         throw new Error(i);
 | |
| }
 | |
| 
 | |
| putFuncToPrivateName(function () { "use strict"; return { thisValue: this, argumentsValue: arguments};  });
 | |
| var foo2 = createTailCallForwardingFuncWith("", "this");
 | |
| var fooNI2 = createTailCallForwardingFuncWith("", "this");
 | |
| noInline(fooNI2);
 | |
| 
 | |
| function baz2() {
 | |
|     return foo2.call(true, 7);
 | |
| }
 | |
| noInline(baz2);
 | |
| 
 | |
| for (let i = 0; i < 100000; i++) {
 | |
|     let result = foo2.call(true, 7);
 | |
|     if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
 | |
|         throw new Error(i);
 | |
|     result = baz2.call();
 | |
|     if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
 | |
|         throw new Error(i);
 | |
|     result = fooNI2.call(true, 7);
 | |
|     if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
 | |
|         throw new Error(i);
 | |
| }
 | |
| 
 | |
| putFuncToPrivateName(function () { "use strict"; return this;  });
 | |
| var foo3 = createTailCallForwardingFuncWith("", "{ thisValue: this, otherValue: 'hello'} ");
 | |
| var fooNI3 = createTailCallForwardingFuncWith("", "{ thisValue: this, otherValue: 'hello'} ");
 | |
| noInline(fooNI3);
 | |
| function baz3() {
 | |
|     return foo3.call(true, 7);
 | |
| }
 | |
| noInline(baz3);
 | |
| 
 | |
| for (let i = 0; i < 100000; i++) {
 | |
|     let result = foo3.call(true, 7);
 | |
|     if (result.thisValue !== true)
 | |
|         throw new Error(i);
 | |
|     result = baz3.call();
 | |
|     if (result.thisValue !== true)
 | |
|         throw new Error(i);
 | |
|     result = fooNI3.call(true, 7);
 | |
|     if (result.thisValue !== true)
 | |
|         throw new Error(i);
 | |
| }
 | |
| 
 | |
| 
 | |
| putFuncToPrivateName(function () { "use strict"; return this;  });
 | |
| let bodyText = `
 | |
| for (let i = 0; i < 100; i++) {
 | |
|     if (a + i === 100)
 | |
|         return a;
 | |
| }
 | |
| `;
 | |
| var foo4 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
 | |
| var fooNI4 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
 | |
| noInline(fooNI4);
 | |
| function baz4() {
 | |
|     return foo4.call(true, 0);
 | |
| }
 | |
| noInline(baz4);
 | |
| 
 | |
| for (let i = 0; i < 100000; i++) {
 | |
|     let result = foo4.call(true, 0);
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
|     result = baz4.call();
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
|     result = fooNI4.call(true, 0);
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
|     result = fooNI4.call(true, 1);
 | |
|     if (result !== 1)
 | |
|         throw new Error(i);
 | |
|     result = fooNI4.call(true, "");
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
| }
 | |
| 
 | |
| var testFunc = function () { "use strict"; return this;  }
 | |
| noInline(testFunc);
 | |
| putFuncToPrivateName(testFunc);
 | |
| 
 | |
| var foo5 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
 | |
| var fooNI5 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
 | |
| noInline(fooNI5);
 | |
| function baz5() {
 | |
|     return foo5.call(true, 0);
 | |
| }
 | |
| noInline(baz5);
 | |
| 
 | |
| for (let i = 0; i < 100000; i++) {
 | |
|     let result = foo5.call(true, 0);
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
|     result = baz5.call();
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
|     result = fooNI5.call(true, 0);
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
|     result = fooNI5.call(true, 1);
 | |
|     if (result !== 1)
 | |
|         throw new Error(i);
 | |
|     result = fooNI5.call(true, "");
 | |
|     if (result.thisValue !== true || result.otherValue !== "hello")
 | |
|         throw new Error(i);
 | |
| }
 | |
| 
 | |
| putFuncToPrivateName(function() { return arguments; });
 | |
| var foo6 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} ");
 | |
| function baz6() {
 | |
|     "use strict"
 | |
|     return foo6.apply(this, arguments);
 | |
| }
 | |
| noInline(baz6);
 | |
| 
 | |
| function arrayEq(a, b) {
 | |
|     if (a.length !== b.length)
 | |
|         throw new Error();
 | |
|     for (let i = 0; i < a.length; i++) {
 | |
|         if (a[i] !== b[i])
 | |
|             throw new Error();
 | |
|     }
 | |
| }
 | |
| let args = ["a", {}, [], Symbol(), 1, 1.234, undefined, null];
 | |
| for (let i = 0; i < 100000; i++) {
 | |
|     let result = baz6.apply(undefined, args);
 | |
|     arrayEq(result, args);
 | |
| }
 |