[JSC] Introduce @putByIdDirectPrivate
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Apr 2018 01:05:40 +0000 (01:05 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Apr 2018 01:05:40 +0000 (01:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184400

Reviewed by Saam Barati.

This patch adds @putByIdDirectPrivate() to use it for builtin JS.
@getByIdDirectPrivate and @putByIdDirectPrivate are pair of intrinsics
accessing to ECMAScript internal fields.

This change removes accidental [[Put]] operation to an object whose [[Prototype]]
has internal fields (not direct properties). By using @getByIdDirectPrivate() and
@putByIdDirectPrivate(), we strongly keep the semantics of the ECMAScript internal
fields that accessing to the internal fields does not traverse prototype chains.

* builtins/ArrayIteratorPrototype.js:
(globalPrivate.arrayIteratorValueNext):
(globalPrivate.arrayIteratorKeyNext):
(globalPrivate.arrayIteratorKeyValueNext):
* builtins/ArrayPrototype.js:
(globalPrivate.createArrayIterator):
* builtins/AsyncFromSyncIteratorPrototype.js:
(globalPrivate.AsyncFromSyncIteratorConstructor):
* builtins/AsyncFunctionPrototype.js:
(globalPrivate.asyncFunctionResume):
* builtins/AsyncGeneratorPrototype.js:
(globalPrivate.asyncGeneratorQueueEnqueue):
(globalPrivate.asyncGeneratorQueueDequeue):
(asyncGeneratorYieldAwaited):
(globalPrivate.asyncGeneratorYield):
(globalPrivate.doAsyncGeneratorBodyCall):
(globalPrivate.asyncGeneratorResumeNext):
* builtins/GeneratorPrototype.js:
(globalPrivate.generatorResume):
* builtins/MapIteratorPrototype.js:
(globalPrivate.mapIteratorNext):
* builtins/MapPrototype.js:
(globalPrivate.createMapIterator):
* builtins/ModuleLoaderPrototype.js:
(forceFulfillPromise):
* builtins/PromiseOperations.js:
(globalPrivate.newHandledRejectedPromise):
(globalPrivate.rejectPromise):
(globalPrivate.fulfillPromise):
(globalPrivate.initializePromise):
* builtins/PromisePrototype.js:
(then):
* builtins/SetIteratorPrototype.js:
(globalPrivate.setIteratorNext):
* builtins/SetPrototype.js:
(globalPrivate.createSetIterator):
* builtins/StringIteratorPrototype.js:
(next):
* bytecode/BytecodeIntrinsicRegistry.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirect):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230459 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
JSTests/stress/put-by-id-direct.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js
Source/JavaScriptCore/builtins/ArrayPrototype.js
Source/JavaScriptCore/builtins/AsyncFromSyncIteratorPrototype.js
Source/JavaScriptCore/builtins/AsyncFunctionPrototype.js
Source/JavaScriptCore/builtins/AsyncGeneratorPrototype.js
Source/JavaScriptCore/builtins/GeneratorPrototype.js
Source/JavaScriptCore/builtins/MapIteratorPrototype.js
Source/JavaScriptCore/builtins/MapPrototype.js
Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js
Source/JavaScriptCore/builtins/PromiseOperations.js
Source/JavaScriptCore/builtins/PromisePrototype.js
Source/JavaScriptCore/builtins/SetIteratorPrototype.js
Source/JavaScriptCore/builtins/SetPrototype.js
Source/JavaScriptCore/builtins/StringIteratorPrototype.js
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

diff --git a/JSTests/stress/put-by-id-direct.js b/JSTests/stress/put-by-id-direct.js
new file mode 100644 (file)
index 0000000..b5c06df
--- /dev/null
@@ -0,0 +1,23 @@
+var createBuiltin = $vm.createBuiltin;
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+(function () {
+    var builtin = createBuiltin(`(function (obj, value) {
+        return @putByIdDirect(obj, "hello", value);
+    })`);
+    noInline(builtin);
+
+    var setValue = null;
+    var object = {
+        __proto__: {
+            hello: 30
+        }
+    };
+    builtin(object, 42);
+    shouldBe(object.hello, 42);
+    shouldBe(object.hasOwnProperty("hello"), true);
+}());
index 350a1e9..aec27d7 100644 (file)
@@ -1,3 +1,62 @@
+2018-04-08  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Introduce @putByIdDirectPrivate
+        https://bugs.webkit.org/show_bug.cgi?id=184400
+
+        Reviewed by Saam Barati.
+
+        This patch adds @putByIdDirectPrivate() to use it for builtin JS.
+        @getByIdDirectPrivate and @putByIdDirectPrivate are pair of intrinsics
+        accessing to ECMAScript internal fields.
+
+        This change removes accidental [[Put]] operation to an object whose [[Prototype]]
+        has internal fields (not direct properties). By using @getByIdDirectPrivate() and
+        @putByIdDirectPrivate(), we strongly keep the semantics of the ECMAScript internal
+        fields that accessing to the internal fields does not traverse prototype chains.
+
+        * builtins/ArrayIteratorPrototype.js:
+        (globalPrivate.arrayIteratorValueNext):
+        (globalPrivate.arrayIteratorKeyNext):
+        (globalPrivate.arrayIteratorKeyValueNext):
+        * builtins/ArrayPrototype.js:
+        (globalPrivate.createArrayIterator):
+        * builtins/AsyncFromSyncIteratorPrototype.js:
+        (globalPrivate.AsyncFromSyncIteratorConstructor):
+        * builtins/AsyncFunctionPrototype.js:
+        (globalPrivate.asyncFunctionResume):
+        * builtins/AsyncGeneratorPrototype.js:
+        (globalPrivate.asyncGeneratorQueueEnqueue):
+        (globalPrivate.asyncGeneratorQueueDequeue):
+        (asyncGeneratorYieldAwaited):
+        (globalPrivate.asyncGeneratorYield):
+        (globalPrivate.doAsyncGeneratorBodyCall):
+        (globalPrivate.asyncGeneratorResumeNext):
+        * builtins/GeneratorPrototype.js:
+        (globalPrivate.generatorResume):
+        * builtins/MapIteratorPrototype.js:
+        (globalPrivate.mapIteratorNext):
+        * builtins/MapPrototype.js:
+        (globalPrivate.createMapIterator):
+        * builtins/ModuleLoaderPrototype.js:
+        (forceFulfillPromise):
+        * builtins/PromiseOperations.js:
+        (globalPrivate.newHandledRejectedPromise):
+        (globalPrivate.rejectPromise):
+        (globalPrivate.fulfillPromise):
+        (globalPrivate.initializePromise):
+        * builtins/PromisePrototype.js:
+        (then):
+        * builtins/SetIteratorPrototype.js:
+        (globalPrivate.setIteratorNext):
+        * builtins/SetPrototype.js:
+        (globalPrivate.createSetIterator):
+        * builtins/StringIteratorPrototype.js:
+        (next):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirect):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate):
+
 2018-04-09  Mark Lam  <mark.lam@apple.com>
 
         Decorate method table entries to support pointer profiling.
index 6dc1e5a..dcb0613 100644 (file)
@@ -49,10 +49,10 @@ function arrayIteratorValueNext()
     if (!@getByIdDirectPrivate(this, "arrayIteratorIsDone")) {
         var index = @getByIdDirectPrivate(this, "arrayIteratorNextIndex");
         var length = array.length >>> 0;
-        if (index >= length) {
-            this.@arrayIteratorIsDone = true;
-        else {
-            this.@arrayIteratorNextIndex = index + 1;
+        if (index >= length)
+            @putByIdDirectPrivate(this, "arrayIteratorIsDone", true);
+        else {
+            @putByIdDirectPrivate(this, "arrayIteratorNextIndex", index + 1);
             done = false;
             value = array[index];
         }
@@ -72,10 +72,10 @@ function arrayIteratorKeyNext()
     if (!@getByIdDirectPrivate(this, "arrayIteratorIsDone")) {
         var index = @getByIdDirectPrivate(this, "arrayIteratorNextIndex");
         var length = array.length >>> 0;
-        if (index >= length) {
-            this.@arrayIteratorIsDone = true;
-        else {
-            this.@arrayIteratorNextIndex = index + 1;
+        if (index >= length)
+            @putByIdDirectPrivate(this, "arrayIteratorIsDone", true);
+        else {
+            @putByIdDirectPrivate(this, "arrayIteratorNextIndex", index + 1);
             done = false;
             value = index;
         }
@@ -95,10 +95,10 @@ function arrayIteratorKeyValueNext()
     if (!@getByIdDirectPrivate(this, "arrayIteratorIsDone")) {
         var index = @getByIdDirectPrivate(this, "arrayIteratorNextIndex");
         var length = array.length >>> 0;
-        if (index >= length) {
-            this.@arrayIteratorIsDone = true;
-        else {
-            this.@arrayIteratorNextIndex = index + 1;
+        if (index >= length)
+            @putByIdDirectPrivate(this, "arrayIteratorIsDone", true);
+        else {
+            @putByIdDirectPrivate(this, "arrayIteratorNextIndex", index + 1);
             done = false;
             value = [ index, array[index] ];
         }
index b1718a4..a3c17ce 100644 (file)
@@ -30,11 +30,11 @@ function createArrayIterator(iteratedObject, kind, iterationFunction)
 {
     "use strict";
 
-    this.@iteratedObject = iteratedObject;
-    this.@arrayIteratorKind = kind;
-    this.@arrayIteratorNextIndex = 0;
-    this.@arrayIteratorNext = iterationFunction;
-    this.@arrayIteratorIsDone = false;
+    @putByIdDirectPrivate(this, "iteratedObject", iteratedObject);
+    @putByIdDirectPrivate(this, "arrayIteratorKind", kind);
+    @putByIdDirectPrivate(this, "arrayIteratorNextIndex", 0);
+    @putByIdDirectPrivate(this, "arrayIteratorNext", iterationFunction);
+    @putByIdDirectPrivate(this, "arrayIteratorIsDone", false);
 }
 
 function values()
index 0421f55..c84bf27 100644 (file)
@@ -161,6 +161,6 @@ function createAsyncFromSyncIterator(syncIterator, nextMethod)
 @constructor
 function AsyncFromSyncIteratorConstructor(syncIterator, nextMethod)
 {
-    this.@syncIterator = syncIterator;
-    this.@nextMethod = nextMethod;
+    @putByIdDirectPrivate(this, "syncIterator", syncIterator);
+    @putByIdDirectPrivate(this, "nextMethod", nextMethod);
 }
index a9a7150..a734877 100644 (file)
@@ -34,15 +34,15 @@ function asyncFunctionResume(generator, promiseCapability, sentValue, resumeMode
         @throwTypeError("Async function illegally resumed");
 
     try {
-        generator.@generatorState = @GeneratorStateExecuting;
+        @putByIdDirectPrivate(generator, "generatorState", @GeneratorStateExecuting);
         value = @getByIdDirectPrivate(generator, "generatorNext").@call(@getByIdDirectPrivate(generator, "generatorThis"), generator, state, sentValue, resumeMode, @getByIdDirectPrivate(generator, "generatorFrame"));
         if (@getByIdDirectPrivate(generator, "generatorState") === @GeneratorStateExecuting) {
-            generator.@generatorState = @GeneratorStateCompleted;
+            @putByIdDirectPrivate(generator, "generatorState", @GeneratorStateCompleted);
             promiseCapability.@resolve(value);
             return promiseCapability.@promise;
         }
     } catch (error) {
-        generator.@generatorState = @GeneratorStateCompleted;
+        @putByIdDirectPrivate(generator, "generatorState", @GeneratorStateCompleted);
         promiseCapability.@reject(error);
         return promiseCapability.@promise;
     }
index f8be92d..f4b0502 100644 (file)
@@ -41,13 +41,13 @@ function asyncGeneratorQueueEnqueue(generator, item)
     if (@getByIdDirectPrivate(generator, "asyncGeneratorQueueFirst") === null) {
         @assert(@getByIdDirectPrivate(generator, "asyncGeneratorQueueLast") === null);
 
-        generator.@asyncGeneratorQueueFirst = item;
-        generator.@asyncGeneratorQueueLast = item;
+        @putByIdDirectPrivate(generator, "asyncGeneratorQueueFirst", item);
+        @putByIdDirectPrivate(generator, "asyncGeneratorQueueLast", item);
     } else {
         var last = @getByIdDirectPrivate(generator, "asyncGeneratorQueueLast");
-        item.@asyncGeneratorQueueItemPrevious = last;
-        last.@asyncGeneratorQueueItemNext = item;
-        generator.@asyncGeneratorQueueLast = item;
+        @putByIdDirectPrivate(item, "asyncGeneratorQueueItemPrevious", last);
+        @putByIdDirectPrivate(last, "asyncGeneratorQueueItemNext", item);
+        @putByIdDirectPrivate(generator, "asyncGeneratorQueueLast", item);
     }
 }
 
@@ -61,10 +61,10 @@ function asyncGeneratorQueueDequeue(generator)
         return null;
 
     var updatedFirst = @getByIdDirectPrivate(result, "asyncGeneratorQueueItemNext");
-    generator.@asyncGeneratorQueueFirst = updatedFirst;
+    @putByIdDirectPrivate(generator, "asyncGeneratorQueueFirst", updatedFirst);
 
     if (updatedFirst === null)
-        generator.@asyncGeneratorQueueLast = null;
+        @putByIdDirectPrivate(generator, "asyncGeneratorQueueLast", null);
 
     return result;
 }
@@ -136,11 +136,11 @@ function asyncGeneratorYield(generator, value, resumeMode)
 
     function asyncGeneratorYieldAwaited(result)
     {
-        generator.@asyncGeneratorSuspendReason = @AsyncGeneratorSuspendReasonYield;
+        @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonYield);
         @asyncGeneratorResolve(generator, result, false);
     }
 
-    generator.@asyncGeneratorSuspendReason = @AsyncGeneratorSuspendReasonAwait;
+    @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonAwait);
 
     @awaitValue(generator, value, asyncGeneratorYieldAwaited);
 
@@ -170,16 +170,16 @@ function doAsyncGeneratorBodyCall(generator, resumeValue, resumeMode)
     let value = @undefined;
     let state = @getByIdDirectPrivate(generator, "generatorState");
 
-    generator.@generatorState = @AsyncGeneratorStateExecuting;
-    generator.@asyncGeneratorSuspendReason = @AsyncGeneratorSuspendReasonNone;
+    @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateExecuting);
+    @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonNone);
 
     try {
         value = @getByIdDirectPrivate(generator, "generatorNext").@call(@getByIdDirectPrivate(generator, "generatorThis"), generator, state, resumeValue, resumeMode, @getByIdDirectPrivate(generator, "generatorFrame"));
         if (@getByIdDirectPrivate(generator, "generatorState") === @AsyncGeneratorStateExecuting)
-            generator.@generatorState = @AsyncGeneratorStateCompleted;
+            @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
     } catch (error) {
-        generator.@generatorState = @AsyncGeneratorStateCompleted;
-        generator.@asyncGeneratorSuspendReason = @AsyncGeneratorSuspendReasonNone;
+        @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
+        @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonNone);
 
         return @asyncGeneratorReject(generator, error);
     }
@@ -196,7 +196,7 @@ function doAsyncGeneratorBodyCall(generator, resumeValue, resumeMode)
         return @asyncGeneratorYield(generator, value, resumeMode);
 
     if (@getByIdDirectPrivate(generator, "generatorState") === @AsyncGeneratorStateCompleted) {
-        generator.@asyncGeneratorSuspendReason = @AsyncGeneratorSuspendReasonNone;
+        @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonNone);
         return @asyncGeneratorResolve(generator, value, true);
     }
 
@@ -224,13 +224,13 @@ function asyncGeneratorResumeNext(generator)
 
     if (next.resumeMode !== @GeneratorResumeModeNormal) {
         if (state === @AsyncGeneratorStateSuspendedStart) {
-            generator.@generatorState = @AsyncGeneratorStateCompleted;
+            @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
             state = @AsyncGeneratorStateCompleted;
         }
 
         if (state === @AsyncGeneratorStateCompleted) {
             if (next.resumeMode === @GeneratorResumeModeReturn) {
-                generator.@generatorState = @AsyncGeneratorStateAwaitingReturn;
+                @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateAwaitingReturn);
 
                 const promiseCapability = @newPromiseCapability(@Promise);
                 promiseCapability.@resolve.@call(@undefined, next.value);
@@ -239,7 +239,7 @@ function asyncGeneratorResumeNext(generator)
                     function (result) { generator.@generatorState = @AsyncGeneratorStateCompleted; @asyncGeneratorResolve(generator, result, true); },
                     function (error) { generator.@generatorState = @AsyncGeneratorStateCompleted; @asyncGeneratorReject(generator, error); });
 
-                throwawayCapabilityPromise.@promiseIsHandled = true;
+                @putByIdDirectPrivate(throwawayCapabilityPromise, "promiseIsHandled", true);
 
                 return @undefined;
             }
index 75d5562..605de34 100644 (file)
@@ -34,14 +34,14 @@ function generatorResume(generator, state, generatorThis, sentValue, value, resu
     var done = state === @GeneratorStateCompleted;
     if (!done) {
         try {
-            generator.@generatorState = @GeneratorStateExecuting;
+            @putByIdDirectPrivate(generator, "generatorState", @GeneratorStateExecuting);
             value = @getByIdDirectPrivate(generator, "generatorNext").@call(generatorThis, generator, state, sentValue, resumeMode, @getByIdDirectPrivate(generator, "generatorFrame"));
             if (@getByIdDirectPrivate(generator, "generatorState") === @GeneratorStateExecuting) {
-                generator.@generatorState = @GeneratorStateCompleted;
+                @putByIdDirectPrivate(generator, "generatorState", @GeneratorStateCompleted);
                 done = true;
             }
         } catch (error) {
-            generator.@generatorState = @GeneratorStateCompleted;
+            @putByIdDirectPrivate(generator, "generatorState", @GeneratorStateCompleted);
             throw error;
         }
     }
index 3dbf935..f1365a6 100644 (file)
@@ -31,7 +31,7 @@ function mapIteratorNext(bucket, kind)
     var value;
 
     bucket = @mapBucketNext(bucket);
-    this.@mapBucket = bucket;
+    @putByIdDirectPrivate(this, "mapBucket", bucket);
     var done = bucket === @sentinelMapBucket;
     if (!done) {
         var key = @mapBucketKey(bucket);
index 4ec041a..c35c5a8 100644 (file)
@@ -30,9 +30,9 @@ function createMapIterator(iteratedObject, kind)
     "use strict";
 
     @assert(@isMap(iteratedObject));
-    this.@iteratedObject = iteratedObject;
-    this.@mapIteratorKind = kind;
-    this.@mapBucket = @mapBucketHead(iteratedObject);
+    @putByIdDirectPrivate(this, "iteratedObject", iteratedObject);
+    @putByIdDirectPrivate(this, "mapIteratorKind", kind);
+    @putByIdDirectPrivate(this, "mapBucket", @mapBucketHead(iteratedObject));
 }
 
 function values()
index ab457ca..93f2225 100644 (file)
@@ -123,7 +123,7 @@ function forceFulfillPromise(promise, value)
 {
     "use strict";
 
-    if (promise.@promiseState === @promiseStatePending)
+    if (@getByIdDirectPrivate(promise, "promiseState") === @promiseStatePending)
         @fulfillPromise(promise, value);
 }
 
index 29469b2..5d566ec 100644 (file)
@@ -88,7 +88,7 @@ function newPromiseCapability(constructor)
 function newHandledRejectedPromise(error)
 {
     let promise = @Promise.@reject(error);
-    promise.@promiseIsHandled = true;
+    @putByIdDirectPrivate(promise, "promiseIsHandled", true);
     return promise;
 }
 
@@ -107,9 +107,9 @@ function rejectPromise(promise, reason)
     "use strict";
 
     var reactions = @getByIdDirectPrivate(promise, "promiseReactions");
-    promise.@promiseResult = reason;
-    promise.@promiseReactions = @undefined;
-    promise.@promiseState = @promiseStateRejected;
+    @putByIdDirectPrivate(promise, "promiseResult", reason);
+    @putByIdDirectPrivate(promise, "promiseReactions", @undefined);
+    @putByIdDirectPrivate(promise, "promiseState", @promiseStateRejected);
 
     @InspectorInstrumentation.promiseRejected(promise, reason, reactions);
 
@@ -125,9 +125,9 @@ function fulfillPromise(promise, value)
     "use strict";
 
     var reactions = @getByIdDirectPrivate(promise, "promiseReactions");
-    promise.@promiseResult = value;
-    promise.@promiseReactions = @undefined;
-    promise.@promiseState = @promiseStateFulfilled;
+    @putByIdDirectPrivate(promise, "promiseResult", value);
+    @putByIdDirectPrivate(promise, "promiseReactions", @undefined);
+    @putByIdDirectPrivate(promise, "promiseState", @promiseStateFulfilled);
 
     @InspectorInstrumentation.promiseFulfilled(promise, value, reactions);
 
@@ -218,9 +218,9 @@ function initializePromise(executor)
     if (typeof executor !== 'function')
         @throwTypeError("Promise constructor takes a function argument");
 
-    this.@promiseState = @promiseStatePending;
-    this.@promiseReactions = [];
-    this.@promiseIsHandled = false;
+    @putByIdDirectPrivate(this, "promiseState", @promiseStatePending);
+    @putByIdDirectPrivate(this, "promiseReactions", []);
+    @putByIdDirectPrivate(this, "promiseIsHandled", false);
 
     var resolvingFunctions = @createResolvingFunctions(this);
     try {
index 6342b40..464642a 100644 (file)
@@ -59,7 +59,7 @@ function then(onFulfilled, onRejected)
         @enqueueJob(@promiseReactionJob, [state, reaction, @getByIdDirectPrivate(this, "promiseResult")]);
     }
 
-    this.@promiseIsHandled = true;
+    @putByIdDirectPrivate(this, "promiseIsHandled", true);
 
     return resultCapability.@promise;
 }
index a06b2a2..6f074dd 100644 (file)
@@ -31,7 +31,7 @@ function setIteratorNext(bucket, kind)
     var value;
 
     bucket = @setBucketNext(bucket);
-    this.@setBucket = bucket;
+    @putByIdDirectPrivate(this, "setBucket", bucket);
     var done = bucket === @sentinelSetBucket;
     if (!done) {
         value = @setBucketKey(bucket);
index ba30170..a650add 100644 (file)
@@ -30,9 +30,9 @@ function createSetIterator(iteratedObject, kind)
     "use strict";
 
     @assert(@isSet(iteratedObject));
-    this.@iteratedObject = iteratedObject;
-    this.@setIteratorKind = kind;
-    this.@setBucket = @setBucketHead(iteratedObject);
+    @putByIdDirectPrivate(this, "iteratedObject", iteratedObject);
+    @putByIdDirectPrivate(this, "setIteratorKind", kind);
+    @putByIdDirectPrivate(this, "setBucket", @setBucketHead(iteratedObject));
 }
 
 function values()
index 3360d2c..2d58205 100644 (file)
@@ -40,9 +40,9 @@ function next()
     var string = @getByIdDirectPrivate(this, "iteratedString");
     if (string !== @undefined) {
         var length = string.length >>> 0;
-        if (position >= length) {
-            this.@iteratedString = @undefined;
-        else {
+        if (position >= length)
+            @putByIdDirectPrivate(this, "iteratedString", @undefined);
+        else {
             done = false;
 
             var first = string.@charCodeAt(position);
@@ -56,7 +56,7 @@ function next()
                     value = string[position] + string[position + 1];
             }
 
-            this.@stringIteratorNextIndex = position + value.length;
+            @putByIdDirectPrivate(this, "stringIteratorNextIndex", position + value.length);
         }
     }
 
index 855016e..eda34ec 100644 (file)
@@ -55,6 +55,8 @@ class Identifier;
     macro(throwRangeError) \
     macro(throwOutOfMemoryError) \
     macro(tryGetById) \
+    macro(putByIdDirect) \
+    macro(putByIdDirectPrivate) \
     macro(putByValDirect) \
     macro(toNumber) \
     macro(toString) \
index 6403942..07a9c90 100644 (file)
@@ -991,6 +991,37 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerato
     return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByIdDirect(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> base = generator.emitNode(node);
+    node = node->m_next;
+    ASSERT(node->m_expr->isString());
+    const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
+    node = node->m_next;
+    RefPtr<RegisterID> value = generator.emitNode(node);
+
+    ASSERT(!node->m_next);
+
+    return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutById(base.get(), ident, value.get(), PropertyNode::KnownDirect));
+}
+
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> base = generator.emitNode(node);
+    node = node->m_next;
+    ASSERT(node->m_expr->isString());
+    const Identifier* ident = generator.vm()->propertyNames->lookUpPrivateName(static_cast<StringNode*>(node->m_expr)->value());
+    ASSERT(ident);
+    node = node->m_next;
+    RefPtr<RegisterID> value = generator.emitNode(node);
+
+    ASSERT(!node->m_next);
+
+    return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutById(base.get(), *ident, value.get(), PropertyNode::KnownDirect));
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;