array-some.tq 5.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
// 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.

namespace array {
  transitioning javascript builtin
  ArraySomeLoopEagerDeoptContinuation(implicit context: Context)(
      receiver: Object, callback: Object, thisArg: Object, initialK: Object,
      length: Object): Object {
    // All continuation points in the optimized some implementation are
    // after the ToObject(O) call that ensures we are dealing with a
    // JSReceiver.
    //
    // Also, this great mass of casts is necessary because the signature
    // of Torque javascript builtins requires Object type for all parameters
    // other than {context}.
    const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
    const callbackfn = Cast<Callable>(callback) otherwise unreachable;
    const numberK = Cast<Number>(initialK) otherwise unreachable;
    const numberLength = Cast<Number>(length) otherwise unreachable;

    return ArraySomeLoopContinuation(
        jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
        numberLength, Undefined);
  }

  transitioning javascript builtin
  ArraySomeLoopLazyDeoptContinuation(implicit context: Context)(
      receiver: Object, callback: Object, thisArg: Object, initialK: Object,
      length: Object, result: Object): Object {
    // All continuation points in the optimized some implementation are
    // after the ToObject(O) call that ensures we are dealing with a
    // JSReceiver.
    const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
    const callbackfn = Cast<Callable>(callback) otherwise unreachable;
    let numberK = Cast<Number>(initialK) otherwise unreachable;
    const numberLength = Cast<Number>(length) otherwise unreachable;

    // This custom lazy deopt point is right after the callback. some() needs
    // to pick up at the next step: if the result is true, then return,
    // otherwise, keep going through the array starting from k + 1.
    if (ToBoolean(result)) {
      return True;
    }

    numberK = numberK + 1;

    return ArraySomeLoopContinuation(
        jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
        numberLength, Undefined);
  }

  transitioning builtin ArraySomeLoopContinuation(implicit context: Context)(
      receiver: JSReceiver, callbackfn: Callable, thisArg: Object,
      array: Object, o: JSReceiver, initialK: Number, length: Number,
      initialTo: Object): Object {
    // 5. Let k be 0.
    // 6. Repeat, while k < len
    for (let k: Number = initialK; k < length; k++) {
      // 6a. Let Pk be ! ToString(k).
      // k is guaranteed to be a positive integer, hence ToString is
      // side-effect free and HasProperty/GetProperty do the conversion inline.

      // 6b. Let kPresent be ? HasProperty(O, Pk).
      const kPresent: Boolean = HasProperty_Inline(o, k);

      // 6c. If kPresent is true, then
      if (kPresent == True) {
        // 6c. i. Let kValue be ? Get(O, Pk).
        const kValue: Object = GetProperty(o, k);

        // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>).
        const result: Object = Call(context, callbackfn, thisArg, kValue, k, o);

        // iii. If selected is true, then...
        if (ToBoolean(result)) {
          return True;
        }
      }

      // 6d. Increase k by 1. (done by the loop).
    }
    return False;
  }

86 87
  transitioning macro FastArraySome(implicit context: Context)(
      o: JSReceiver, len: Number, callbackfn: Callable, thisArg: Object): Object
88 89
      labels Bailout(Smi) {
    let k: Smi = 0;
90 91
    const smiLen = Cast<Smi>(len) otherwise goto Bailout(k);
    let fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k);
92
    let fastOW = NewFastJSArrayWitness(fastO);
93 94

    // Build a fast loop over the smi array.
95 96
    for (; k < smiLen; k++) {
      fastOW.Recheck() otherwise goto Bailout(k);
97

98
      // Ensure that we haven't walked beyond a possibly updated length.
99 100 101 102 103 104
      if (k >= fastOW.Get().length) goto Bailout(k);
      const value: Object = fastOW.LoadElementNoHole(k) otherwise continue;
      const result: Object =
          Call(context, callbackfn, thisArg, value, k, fastOW.Get());
      if (ToBoolean(result)) {
        return True;
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
      }
    }
    return False;
  }

  // https://tc39.github.io/ecma262/#sec-array.prototype.some
  transitioning javascript builtin
  ArraySome(implicit context: Context)(receiver: Object, ...arguments): Object {
    try {
      if (IsNullOrUndefined(receiver)) {
        goto NullOrUndefinedError;
      }

      // 1. Let O be ? ToObject(this value).
      const o: JSReceiver = ToObject_Inline(context, receiver);

      // 2. Let len be ? ToLength(? Get(O, "length")).
      const len: Number = GetLengthProperty(o);

      // 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
      if (arguments.length == 0) {
        goto TypeError;
      }
      const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError;

      // 4. If thisArg is present, let T be thisArg; else let T be undefined.
      const thisArg: Object = arguments.length > 1 ? arguments[1] : Undefined;

      // Special cases.
      try {
        return FastArraySome(o, len, callbackfn, thisArg)
            otherwise Bailout;
      }
      label Bailout(kValue: Smi) deferred {
        return ArraySomeLoopContinuation(
            o, callbackfn, thisArg, Undefined, o, kValue, len, Undefined);
      }
    }
    label TypeError deferred {
144
      ThrowTypeError(kCalledNonCallable, arguments[0]);
145 146
    }
    label NullOrUndefinedError deferred {
147
      ThrowTypeError(kCalledOnNullOrUndefined, 'Array.prototype.some');
148 149 150
    }
  }
}