<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>84074</bug_id>
          
          <creation_ts>2012-04-16 14:03:14 -0700</creation_ts>
          <short_desc>[meta][V8] Pass Isolate around in V8 bindings</short_desc>
          <delta_ts>2014-03-02 09:33:17 -0800</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>WebCore JavaScript</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>INVALID</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          <dependson>84077</dependson>
    
    <dependson>84103</dependson>
    
    <dependson>84161</dependson>
    
    <dependson>84173</dependson>
    
    <dependson>84202</dependson>
    
    <dependson>84250</dependson>
    
    <dependson>84257</dependson>
    
    <dependson>84259</dependson>
    
    <dependson>84261</dependson>
    
    <dependson>84269</dependson>
    
    <dependson>84271</dependson>
    
    <dependson>84273</dependson>
    
    <dependson>84277</dependson>
    
    <dependson>84295</dependson>
    
    <dependson>84299</dependson>
    
    <dependson>84310</dependson>
    
    <dependson>84627</dependson>
    
    <dependson>84628</dependson>
    
    <dependson>84637</dependson>
    
    <dependson>84650</dependson>
    
    <dependson>84656</dependson>
    
    <dependson>84658</dependson>
    
    <dependson>84660</dependson>
    
    <dependson>84662</dependson>
    
    <dependson>84663</dependson>
    
    <dependson>84736</dependson>
    
    <dependson>84739</dependson>
    
    <dependson>84753</dependson>
    
    <dependson>84757</dependson>
    
    <dependson>84758</dependson>
    
    <dependson>84787</dependson>
    
    <dependson>84918</dependson>
    
    <dependson>84919</dependson>
    
    <dependson>84921</dependson>
    
    <dependson>84922</dependson>
    
    <dependson>84923</dependson>
    
    <dependson>85022</dependson>
    
    <dependson>85023</dependson>
    
    <dependson>85097</dependson>
    
    <dependson>85102</dependson>
    
    <dependson>85205</dependson>
    
    <dependson>85207</dependson>
    
    <dependson>85329</dependson>
    
    <dependson>86558</dependson>
    
    <dependson>86566</dependson>
    
    <dependson>86570</dependson>
    
    <dependson>86576</dependson>
    
    <dependson>86579</dependson>
    
    <dependson>86744</dependson>
    
    <dependson>86794</dependson>
    
    <dependson>86802</dependson>
    
    <dependson>86976</dependson>
    
    <dependson>86977</dependson>
    
    <dependson>86978</dependson>
    
    <dependson>86979</dependson>
    
    <dependson>86980</dependson>
    
    <dependson>86981</dependson>
    
    <dependson>86983</dependson>
    
    <dependson>87070</dependson>
    
    <dependson>87111</dependson>
    
    <dependson>87193</dependson>
    
    <dependson>87202</dependson>
    
    <dependson>87204</dependson>
    
    <dependson>87207</dependson>
    
    <dependson>87209</dependson>
    
    <dependson>87689</dependson>
    
    <dependson>87692</dependson>
    
    <dependson>87713</dependson>
    
    <dependson>87807</dependson>
    
    <dependson>87809</dependson>
    
    <dependson>87810</dependson>
    
    <dependson>87812</dependson>
    
    <dependson>87814</dependson>
    
    <dependson>87820</dependson>
    
    <dependson>87825</dependson>
    
    <dependson>87948</dependson>
    
    <dependson>90238</dependson>
    
    <dependson>90242</dependson>
    
    <dependson>93315</dependson>
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Kentaro Hara">haraken</reporter>
          <assigned_to name="Kentaro Hara">haraken</assigned_to>
          <cc>abarth</cc>
    
    <cc>arv</cc>
    
    <cc>dglazkov</cc>
    
    <cc>japhet</cc>
    
    <cc>krit</cc>
    
    <cc>yurys</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>603415</commentid>
    <comment_count>0</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-04-16 14:03:14 -0700</bug_when>
    <thetext>Currently, V8 and V8 bindings are looking up Isolate here and there, and this is one of the main performance bottlenecks in DOM attribute getters/setters and methods.

Now V8 exposes Isolate as AccessorInfo::GetIsolate() and Arguments::GetIsolate(). By passing the Isolate around, we can remove Isolate lookups from V8 and V8 bindings.

In terms of performance, the first objective is to remove Isolate lookup from v8ExternalString() and getDOMDataStore().</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>603420</commentid>
    <comment_count>1</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-04-16 14:04:10 -0700</bug_when>
    <thetext>I&apos;ll upload patches step by step. abarth@ is on vacation for two weeks, and I am happy if anyone would review them:)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>604055</commentid>
    <comment_count>2</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-04-17 08:54:53 -0700</bug_when>
    <thetext>The objective: Remove Isolate look-up from get{DOMNode,ActiveDOMNode,DOMObject,ActiveDOMObject}Map().

I&apos;ll land patches in the following steps:

[1] Add an optional Isolate argument to toV8(), toV8Slow(), wrap() and wrapSlow(). e.g. toV8(XXX* impl, Isolate* isolate = 0);
[2] Rewrite all callers of toV8(), toV8Slow(), wrap() and wrapSlow() so that they pass Isolate to these methods.
[3] Make the Isolate argument non-optional. i.e. toV8(XXX* impl, Isolate* isolate);
[4] Pass Isolate to get{DOMNode,ActiveDOMNode,DOMObject,ActiveDOMObject}Map() and remove Isolate look-up.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>605268</commentid>
    <comment_count>3</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-04-18 18:02:37 -0700</bug_when>
    <thetext>Progress update: I&apos;ve uploaded a bunch of patches to pass Isolate to toV8(). Regarding toV8(), the remaining tasks are as follows:

(a) setDOMException() and throwError() can call toV8(). Thus we should pass Isolate to setDOMException() and throwError(). This requires a bunch of patches.

(b) SerializedScriptValue::create() can call toV8(). We should pass Isolate to SerializedScriptValue::create(). This requires a bunch of patches.

(c) Even after (a) and (b), there will be ~30 toV8()s without Isolate, but I think we can leave them as-is (unless the toV8() is a performance bottleneck). Some toV8()s are difficult to receive Isolate because they can be called from the context of WebCore (e.g. ScriptController.cpp, ScriptObject.cpp, V8NodeFilterCondition.cpp, etc).

I&apos;ll upload patches for (a) and (b).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>608240</commentid>
    <comment_count>4</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-04-23 17:40:35 -0700</bug_when>
    <thetext>(In reply to comment #3)
&gt; Progress update: I&apos;ve uploaded a bunch of patches to pass Isolate to toV8(). Regarding toV8(), the remaining tasks are as follows:
&gt; 
&gt; (a) setDOMException() and throwError() can call toV8(). Thus we should pass Isolate to setDOMException() and throwError(). This requires a bunch of patches.
&gt; 
&gt; (b) SerializedScriptValue::create() can call toV8(). We should pass Isolate to SerializedScriptValue::create(). This requires a bunch of patches.
&gt; 
&gt; (c) Even after (a) and (b), there will be ~30 toV8()s without Isolate, but I think we can leave them as-is (unless the toV8() is a performance bottleneck). Some toV8()s are difficult to receive Isolate because they can be called from the context of WebCore (e.g. ScriptController.cpp, ScriptObject.cpp, V8NodeFilterCondition.cpp, etc).
&gt; 
&gt; I&apos;ll upload patches for (a) and (b).

Progress update:

- setDOMException() =&gt; Uploaded almost all patches.
- throwError() =&gt; We need to refactor and fix bugs before passing Isolate around. The refactoring and bug-fixing are on-going.
- SerializedScriptValue::create() =&gt; Started.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>624974</commentid>
    <comment_count>5</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-15 22:07:53 -0700</bug_when>
    <thetext>Progress update:

- toV8(isolate) =&gt; Done
- wrap(isolate) =&gt; Done
- getDOMXXXMap(isolate) =&gt; Done
- setDOMException(isolate) =&gt; Done
- SerializedScriptValue::create(isolate) =&gt; Done
- throwError(isolate) =&gt; Started
- Pass Isolate to V8 basic values (e.g. v8::Null(), v8::Integer::New()) =&gt; Not started

Before starting the work for throwError(isolate), I think we should refactor a series of throwError().

The current world:

- throwError(&quot;message&quot;) is the same as throwError(TypeError, &quot;message&quot;)
- throwError(&quot;message&quot;, TypeError) is the same as throwError(TypeError, &quot;message&quot;)
- throwTypeError() is the same as throwError(TypeError, &quot;Type error&quot;)

The refactored world:

- Basically, only throwError(TypeError, &quot;message&quot;) is served
- For syntax sugar, throwTypeError(&quot;message&quot;) is served</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>630382</commentid>
    <comment_count>6</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-22 08:16:30 -0700</bug_when>
    <thetext>Progress update:

- toV8(isolate) =&gt; Done
- wrap(isolate) =&gt; Done
- getDOMXXXMap(isolate) =&gt; Done
- setDOMException(isolate) =&gt; Done
- throwError(isolate) =&gt; Done
- SerializedScriptValue::create(isolate) =&gt; Done
- Pass Isolate to V8 basic values (e.g. v8::Null(), v8::Integer::New()) =&gt; Started</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>631306</commentid>
    <comment_count>7</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-23 00:08:08 -0700</bug_when>
    <thetext>&gt; Pass Isolate to V8 basic values (e.g. v8::Null(), v8::Integer::New()) =&gt; Started

Let me stop the work for a moment.

In Null(isolate), &apos;isolate&apos; can be 0 if we cannot retrieve the Isolate (e.g. in an event handler invoked from the context of WebCore). In that case, Null(0) is called, and it crashes...

I filed a bug in V8 to make Null(0), Undefined(0), etc work correctly (http://code.google.com/p/v8/issues/detail?id=2148). After the bug is fixed in V8, I&apos;ll restart the work.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>631628</commentid>
    <comment_count>8</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-23 06:59:20 -0700</bug_when>
    <thetext>(In reply to comment #7)
&gt; I filed a bug in V8 to make Null(0), Undefined(0), etc work correctly (http://code.google.com/p/v8/issues/detail?id=2148). After the bug is fixed in V8, I&apos;ll restart the work.

That being said, the V8 team might not want to implement the NULL check in Null(Isolate*), since it can decrease performance. More discussion here: http://code.google.com/p/v8/issues/detail?can=2&amp;start=0&amp;num=100&amp;q=&amp;colspec=ID%20Type%20Status%20Priority%20Owner%20Summary%20HW%20OS%20Area%20Stars&amp;groupby=&amp;sort=&amp;id=2148</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>631956</commentid>
    <comment_count>9</comment_count>
    <who name="Adam Barth">abarth</who>
    <bug_when>2012-05-23 13:16:06 -0700</bug_when>
    <thetext>Eventually we will probably want to make the isolate parameter mandatory, so perhaps it&apos;s better to do the null check in an inline function on the WebKit side of the API.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>632213</commentid>
    <comment_count>10</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-23 17:05:05 -0700</bug_when>
    <thetext>Any of Null(Isolate*) patches has caused crash bugs (https://bugs.webkit.org/show_bug.cgi?id=87258). For the time being, let me roll out all Null(Isolate*) patches, i.e. r118133, r118129, r118120 and r118134.

I&apos;ll re-land them using an inline function to do the NULL check.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>632253</commentid>
    <comment_count>11</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-23 17:51:56 -0700</bug_when>
    <thetext>(In reply to comment #9)
&gt; Eventually we will probably want to make the isolate parameter mandatory, so perhaps it&apos;s better to do the null check in an inline function on the WebKit side of the API.

Sounds reasonable. Let&apos;s implement the NULL check macro and use it for v8::Null(isolate), v8::Undefined(isolate) etc.

FYI: I&apos;ve confirmed that the performance of Null(isolate) regresses by 1.6%, if V8 inserts the NULL check inside Null(isolate):
http://code.google.com/p/v8/issues/detail?id=2148#c4</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>634993</commentid>
    <comment_count>12</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-28 01:38:55 -0700</bug_when>
    <thetext>(In reply to comment #11)
&gt; (In reply to comment #9)
&gt; &gt; Eventually we will probably want to make the isolate parameter mandatory, so perhaps it&apos;s better to do the null check in an inline function on the WebKit side of the API.
&gt; 
&gt; Sounds reasonable. Let&apos;s implement the NULL check macro and use it for v8::Null(isolate), v8::Undefined(isolate) etc.

abarth:

(1) Should we replace _all_ v8::Null(isolate)s to the macro? Or should we replace only v8::Null(isolate)s whose isolate can be 0? I would prefer the latter in terms of performance. However, the concern is that if we mix v8::Null(isolate) and the macro, people might misuse v8::Null(isolate) at the place where the macro should be used, which will cause a crash bug.

(2) What&apos;s the name of the macro? V8_NULL(isolate) is OK?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>635006</commentid>
    <comment_count>13</comment_count>
    <who name="Adam Barth">abarth</who>
    <bug_when>2012-05-28 01:53:00 -0700</bug_when>
    <thetext>&gt; (1) Should we replace _all_ v8::Null(isolate)s to the macro? Or should we replace only v8::Null(isolate)s whose isolate can be 0? I would prefer the latter in terms of performance. However, the concern is that if we mix v8::Null(isolate) and the macro, people might misuse v8::Null(isolate) at the place where the macro should be used, which will cause a crash bug.

IMHO, we should just use it where isolate can be null.  I&apos;d like to get to the point where we never pass around a null isolate, so we can gradually remove the macro as we get better about using non-null isolates.  We just need to be careful not to cause crashes in the meantime.

&gt; (2) What&apos;s the name of the macro? V8_NULL(isolate) is OK?

Rather than using a macro, perhaps we should use an inline function?  That should generate the same code as a macro but use better C++.  Perhaps we could call it v8Null(isolate) similar to v8String(..) ?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>635009</commentid>
    <comment_count>14</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-28 01:56:31 -0700</bug_when>
    <thetext>(In reply to comment #13)
&gt; IMHO, we should just use it where isolate can be null.  I&apos;d like to get to the point where we never pass around a null isolate, so we can gradually remove the macro as we get better about using non-null isolates.  We just need to be careful not to cause crashes in the meantime.

OK, makes sense.

&gt; &gt; (2) What&apos;s the name of the macro? V8_NULL(isolate) is OK?
&gt; 
&gt; Rather than using a macro, perhaps we should use an inline function?  That should generate the same code as a macro but use better C++.  Perhaps we could call it v8Null(isolate) similar to v8String(..) ?

Sure.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>636867</commentid>
    <comment_count>15</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-29 22:46:05 -0700</bug_when>
    <thetext>How should we treat v8::Undefined() and v8::Handle&lt;v8::Value&gt;()? Currently v8::Undefined() and v8::Handle&lt;v8::Value&gt;() are mixed to represent undefined.

I manually hacked generated code and measured the performance of v8::Undefined(), v8::Undefined(isolate), v8UndefinedWithCheck(isolate), and v8::Handle&lt;v8::Value&gt;().

// 14.6 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    return v8::Undefined();
}

// 8.4 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    return v8::Undefined(info.GetIsolate());
}

// 8.9 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    v8::Isolate* isolate = info.GetIsolate();
    return isolate ? v8::Undefined(isolate) : v8::Handle&lt;v8::Value&gt;();  // This simulates v8UndefinedWithCheck(isolate)
}

// 9.1 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    return v8::Handle&lt;v8::Value&gt;();
}


Keeping the performance in mind, I guess the best approach would be as follows:

(1) Replace all v8::Handle&lt;v8::Value&gt;() with v8::Undefined().
(2) Replace all v8::Undefined() with v8::Undefined(isolate) where isolate cannot be 0.
(3) Replace all v8::Undefined() with v8UndefinedWithCheck(isolate) where isolate can be 0.

Consequently, the fast path will be 8.4 ns and the slow path will be 8.9 ns. The mixture of v8::Undefined() and v8::Handle&lt;v8::Value&gt;() will be also resolved. WDYT?

Another approach is just to use v8::Handle&lt;v8::Value&gt;() everywhere. This will simplify the code most. But in this case both the fast path and the slow path will be 9.1 ns.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>637446</commentid>
    <comment_count>16</comment_count>
    <who name="Adam Barth">abarth</who>
    <bug_when>2012-05-30 11:12:27 -0700</bug_when>
    <thetext>Is it worth understanding why v8::Undefined() is a different speed than v8::Handle&lt;v8::Value&gt;() ?  It seems like the two should be the same speed since they do the same thing.  Ideally, we&apos;d make them be the same speed as v8::Undefined(info.GetIsolate()), which also does the same thing.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>638188</commentid>
    <comment_count>17</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-31 03:22:19 -0700</bug_when>
    <thetext>abarth:

// [A] div.xxx = 9.1 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    return v8::Handle&lt;v8::Value&gt;();
}

// [B] div.xxx = 9.0 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    static v8::Handle&lt;v8::Value&gt; v = v8::Handle&lt;v8::Value&gt;();
    return v;
}

// [C] div.xxx = 8.4 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    return v8::Undefined(info.GetIsolate());
}

// [D] div.xxx = 8.4 ns
v8::Handle&lt;v8::Value&gt; xxxAttrGetter(..., info) {
    static v8::Handle&lt;v8::Value&gt; v = v8::Undefined(info.GetIsolate());
    return v;
}


Comparing [A] and [B], v8::Handle&lt;v8::Value&gt;() itself is zero overhead. Comparing [C] and [D], v8::Undefined(info.GetIsolate()) itself is also zero overhead. Comparing [B] and [D], if we return v8::Handle&lt;v8::Value&gt;(), there seems to be some additional work in V8 compared to the case where we return v8::Undefined(info.GetIsolate()). Maybe V8 needs to internally generate an undefined value if we return v8::Handle&lt;v8::Value&gt;()??

Anyway I&apos;ll discuss it with the V8 team.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>638191</commentid>
    <comment_count>18</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-05-31 03:26:24 -0700</bug_when>
    <thetext>Progress update: I think that I&apos;ve done 80%~ of the whole work.

What is left is v8::Undefined() and v8::Integer::New(). As discussed above, v8::Undefined() requires a discussion with the V8 team. v8::Integer::New() does not yet have an Isolate version of API. So I&apos;ll stop this work for a moment until the work is unblocked.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>673725</commentid>
    <comment_count>19</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-07-19 11:27:17 -0700</bug_when>
    <thetext>According to the V8 team, v8::Handle&lt;v8::Value&gt;() should be as fast as v8::Undefined(info.GetIsolate()). I filed a bug here: http://code.google.com/p/v8/issues/detail?id=2245

If v8::Handle&lt;v8::Value&gt;() becomes as fast as v8::Undefined(info.GetIsolate()), we can use v8::Handle&lt;v8::Value&gt;() everywhere regardless of isolate, which will make codebase much simpler.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>677891</commentid>
    <comment_count>20</comment_count>
    <who name="Kentaro Hara">haraken</who>
    <bug_when>2012-07-25 04:04:51 -0700</bug_when>
    <thetext>(In reply to comment #19)
&gt; According to the V8 team, v8::Handle&lt;v8::Value&gt;() should be as fast as v8::Undefined(info.GetIsolate()). I filed a bug here: http://code.google.com/p/v8/issues/detail?id=2245

The V8 team found that this performance difference is caused by branch prediction miss. Interesting. (http://code.google.com/p/v8/issues/detail?id=2245#c5)</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>