Home | History | Annotate | Download | only in strong
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Flags: --strong-mode --allow-natives-syntax
      6 
      7 function getSloppyArguments() {
      8   return arguments;
      9 }
     10 
     11 function getObjects() {
     12   "use strict";
     13   return [
     14     {},
     15     Object(""),
     16     [],
     17     (function(){}),
     18     (class Foo {}),
     19     getSloppyArguments(),
     20     arguments,
     21     new Date(),
     22   ];
     23 }
     24 
     25 // TODO(conradw): add tests for non-inheritance once semantics are implemented.
     26 function getNonInheritingObjects() {
     27   "use strong";
     28   return [
     29     Object(""),
     30     [],
     31     // TODO(conradw): uncomment and correct test once Object.defineProperty is
     32     // fixed.
     33     // new Uint32Array(0)
     34   ];
     35 }
     36 
     37 function readFromObjectElementSloppy(o) {
     38   return o[0];
     39 }
     40 
     41 function readFromObjectElementSparseSloppy(o) {
     42   return o[100000];
     43 }
     44 
     45 function readFromObjectElementNonSmiSloppy(o) {
     46   return o[3000000000];
     47 }
     48 
     49 function readFromObjectNonIndexSloppy(o) {
     50   return o[5000000000];
     51 }
     52 
     53 function readFromObjectElementVarSloppy(o) {
     54   var a = 0;
     55   return o[a];
     56 }
     57 
     58 function readFromObjectElementSparseVarSloppy(o) {
     59   var a = 100000;
     60   return o[a];
     61 }
     62 
     63 function readFromObjectElementNonSmiVarSloppy(o) {
     64   var a = 3000000000;
     65   return o[a];
     66 }
     67 
     68 function readFromObjectNonIndexVarSloppy(o) {
     69   var a = 5000000000;
     70   return o[a];
     71 }
     72 
     73 function readFromObjectElementStrong(o) {
     74   "use strong";
     75   return o[0];
     76 }
     77 
     78 function readFromObjectElementSparseStrong(o) {
     79   "use strong";
     80   return o[100000];
     81 }
     82 
     83 function readFromObjectElementNonSmiStrong(o) {
     84   "use strong";
     85   return o[3000000000];
     86 }
     87 
     88 function readFromObjectNonIndexStrong(o) {
     89   "use strong";
     90   return o[5000000000];
     91 }
     92 
     93 function readFromObjectElementLetStrong(o) {
     94   "use strong";
     95   let a = 0;
     96   return o[a];
     97 }
     98 
     99 function readFromObjectElementSparseLetStrong(o) {
    100   "use strong";
    101   let a = 100000;
    102   return o[a];
    103 }
    104 
    105 function readFromObjectElementNonSmiLetStrong(o) {
    106   "use strong";
    107   let a = 3000000000;
    108   return o[a];
    109 }
    110 
    111 function readFromObjectNonIndexLetStrong(o) {
    112   "use strong";
    113   let a = 5000000000;
    114   return o[a];
    115 }
    116 
    117 function getDescs(x) {
    118   return [
    119     {value: x},
    120     {configurable: true, enumerable: true, writable: true, value: x},
    121     {configurable: true, enumerable: true, get: (function() {return x}) },
    122   ];
    123 }
    124 
    125 function assertStrongSemantics(func, object) {
    126   %DeoptimizeFunction(func);
    127   %ClearFunctionTypeFeedback(func);
    128   assertThrows(function(){func(object)}, TypeError);
    129   assertThrows(function(){func(object)}, TypeError);
    130   assertThrows(function(){func(object)}, TypeError);
    131   %OptimizeFunctionOnNextCall(func);
    132   assertThrows(function(){func(object)}, TypeError);
    133   %DeoptimizeFunction(func);
    134   assertThrows(function(){func(object)}, TypeError);
    135 }
    136 
    137 function assertSloppySemantics(func, object) {
    138   %DeoptimizeFunction(func);
    139   %ClearFunctionTypeFeedback(func);
    140   assertDoesNotThrow(function(){func(object)});
    141   assertDoesNotThrow(function(){func(object)});
    142   assertDoesNotThrow(function(){func(object)});
    143   %OptimizeFunctionOnNextCall(func);
    144   assertDoesNotThrow(function(){func(object)});
    145   %DeoptimizeFunction(func);
    146   assertDoesNotThrow(function(){func(object)});
    147 }
    148 
    149 (function () {
    150   "use strict";
    151 
    152   let goodKeys = [
    153     "0",
    154     "100000",
    155     "3000000000",
    156     "5000000000"
    157   ]
    158 
    159   let badKeys = [
    160     "bar",
    161     "1",
    162     "100001",
    163     "3000000001",
    164     "5000000001"
    165   ];
    166 
    167   let values = [
    168     "string",
    169     1,
    170     100001,
    171     30000000001,
    172     50000000001,
    173     NaN,
    174     {},
    175     undefined
    176   ];
    177 
    178   let badAccessorDescs = [
    179     { set: (function(){}) },
    180     { configurable: true, enumerable: true, set: (function(){}) }
    181   ];
    182 
    183   let readSloppy = [
    184     readFromObjectElementSloppy,
    185     readFromObjectElementSparseSloppy,
    186     readFromObjectElementNonSmiSloppy,
    187     readFromObjectNonIndexSloppy,
    188     readFromObjectElementVarSloppy,
    189     readFromObjectElementSparseVarSloppy,
    190     readFromObjectElementNonSmiVarSloppy,
    191     readFromObjectNonIndexVarSloppy
    192   ];
    193 
    194   let readStrong = [
    195     readFromObjectElementStrong,
    196     readFromObjectElementSparseStrong,
    197     readFromObjectElementNonSmiStrong,
    198     readFromObjectNonIndexStrong,
    199     readFromObjectElementLetStrong,
    200     readFromObjectElementSparseLetStrong,
    201     readFromObjectElementNonSmiLetStrong,
    202     readFromObjectNonIndexLetStrong
    203   ];
    204 
    205   let dummyProto = {};
    206   for (let key of goodKeys) {
    207     Object.defineProperty(dummyProto, key, { value: undefined });
    208   }
    209 
    210   // After altering the backing store, accessing a missing property should still
    211   // throw.
    212   for (let key of badKeys) {
    213     for (let value of values) {
    214       for (let desc of getDescs(value)) {
    215         let objects = getObjects();
    216         let nonInheritingObjects = getNonInheritingObjects();
    217         for (let object of objects.concat(nonInheritingObjects)) {
    218           Object.defineProperty(object, key, desc);
    219           for (let func of readStrong) {
    220             assertStrongSemantics(func, object);
    221           }
    222           for (let func of readSloppy) {
    223             assertSloppySemantics(func, object);
    224           }
    225         }
    226         for (let object of objects) {
    227           // Accessing a property which is on the prototype chain of the object
    228           // should not throw.
    229           object.__proto__ = dummyProto;
    230           for (let key of goodKeys) {
    231             for (let func of readStrong.concat(readSloppy)) {
    232               assertSloppySemantics(func, object);
    233             }
    234           }
    235         }
    236       }
    237     }
    238   }
    239 })();
    240