Re: [v8-users] Can somebody explain the --predictable flag?

2017-09-24 Thread Jakob Kummerow
Essentially, --predictable turns off anything in V8 that is known to cause
changes in behavior from one run to the next: multiple thread usage (it
restricts V8 to using *just one thread*, no background threads at all), the
random number generator in Math.random(), and anything else we could think
of (which I can't think of right now ;-) ). It is intended for debugging
flaky problems (by making them reproducible), but sometimes it has the side
effect of hiding flaky problems...

On Sun, Sep 24, 2017 at 8:52 PM, Brandon Jonson 
wrote:

> Hello All!
>
> I have V8 embedded in a multi threaded app. The app uses locker/unlocker
> and all seems to work just fine in those regards (no locker errors or full
> on app crashes). I do have an edge case though I thought I'd get some input
> on. If I basically pound the isolate (utilizing locker of course) from
> multiple threads v8 will eventually FREEZE on a resolve and never respond.
> Below is the line it freezes on...
>
> resolver->Resolve(String::NewFromUtf8(isolate, msg));
>
> It doesn't crash the app...it just won't ever move on from that line of
> code, waiting for V8. It's as if V8 decided to just not respond anymore but
> I'm not seeing any indication of an error. Also if I change this to an
> actual function call it will do the same thing (so not necessarily Promise
> related).
>
> The crazy thing is that when I add the --predictable flag that issue goes
> away. I understand they replaced set_max_available_threads, allowing the
> Platform to handle the work and that this --predictable flag basically
> forces the Platform to use one thread for background processes (I think).
> My assumption the freeze is occurring because of too many threads?
>
> Anyway I was hoping somebody a hell of a lot smarter than me could explain
> what this flag is changing and what fresh hell did I open myself up to by
> enabling it.
>
> Thank You!
>
> --
> --
> v8-users mailing list
> v8-users@googlegroups.com
> http://groups.google.com/group/v8-users
> ---
> You received this message because you are subscribed to the Google Groups
> "v8-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to v8-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[v8-users] Can somebody explain the --predictable flag?

2017-09-24 Thread Brandon Jonson
Hello All! 

I have V8 embedded in a multi threaded app. The app uses locker/unlocker 
and all seems to work just fine in those regards (no locker errors or full 
on app crashes). I do have an edge case though I thought I'd get some input 
on. If I basically pound the isolate (utilizing locker of course) from 
multiple threads v8 will eventually FREEZE on a resolve and never respond. 
Below is the line it freezes on...

resolver->Resolve(String::NewFromUtf8(isolate, msg));

It doesn't crash the app...it just won't ever move on from that line of 
code, waiting for V8. It's as if V8 decided to just not respond anymore but 
I'm not seeing any indication of an error. Also if I change this to an 
actual function call it will do the same thing (so not necessarily Promise 
related).

The crazy thing is that when I add the --predictable flag that issue goes 
away. I understand they replaced set_max_available_threads, allowing the 
Platform to handle the work and that this --predictable flag basically 
forces the Platform to use one thread for background processes (I think). 
My assumption the freeze is occurring because of too many threads?  

Anyway I was hoping somebody a hell of a lot smarter than me could explain 
what this flag is changing and what fresh hell did I open myself up to by 
enabling it. 

Thank You! 

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [v8-users] Re: Is "extend" keyword a performance antipattern???

2017-09-24 Thread Jakob Kummerow
"extends" is not an anti-pattern.

Of course monomorphic code is fastest. Polymorphic/megamorphic loads and
stores have to do more work (specifically, dynamic dispatch), which is
going to take a bit more time. Class hierarchies are one way how developers
*can* create polymorphic code; what you have here is an example of that.
But that doesn't mean that inheritance itself is a problem, or that
polymorphism is a problem.

The reason this is different from C++ vtables is because JavaScript isn't
C++. JavaScript is a dynamic language, and engines must strike a balance
between achieving fast execution when the object hierarchies are not
modified much, and still having acceptable performance when developers make
use of JavaScript's dynamic capabilities and do modify the object hierarchy
at runtime. So engines should not have internal mechanics that are too
rigid, and would cause huge performance drops when code does something
valid but "unexpected". It's easy to point at one pattern and say "clearly
this should be handled better", but when you look at a variety of large
codebases, they use so many different patterns that it becomes very unclear
what internal object representation model would work best on average.

FWIW, the original example is essentially equivalent to simple
"traditional" polymorphic patterns like the following, which uses no
inheritance and no "extends":

function DoIt(obj) { obj.done++; }

function Cat() {}
function Dog() {}
// etc.

var c = new Cat();
DoIt(c);  // Only one type so far -> monomorphic
var d = new Dog();
DoIt(d);  // Two types -> polymorphic
// etc.

On Sun, Sep 24, 2017 at 3:51 PM, Caitlin Potter  wrote:

> So yes, the load/store for `this.done++` can't be reduced to simple
> machine ops when `doIt` is megamorphic, as far as I can tell. (5+ receiver
> maps should make the load/stores megamorphic, or at least that's what
> https://github.com/v8/v8/blob/9a0d5d9700ee269cbe7abee6d62733
> 163dadac14/src/ic/ic.h#L33-L35 seems to indicate).
>
> That doesn't necessarily mean LoadIC is going to be slow, I guess it
> depends on how often you the receiver map is missing from the cache. Slower
> than the inlined monomorphic in-object field load/store, but probably not
> "anti-pattern" slow.
>
> I could be wrong about this, but I think the CallIC for individual calls
> to `doIt` can be inlined with different type feedback information for the
> load/store, so if that shows up in hot code which is monomorphic or
> polymorphic, it might produce better code than your example there.
>
> That said, I'm half guessing about all of this, so I'll leave the rest of
> this thread for more knowledgeable people.
>
> On Sunday, September 24, 2017 at 12:07:58 PM UTC-4, Bogdan Orlov wrote:
>>
>> After removing all intermediate %OptimizeFunctionOnNextCall()  and
>> putting at the end (after usage of all Animal subclasses for enough
>> feedback) like this
>>
>> class Animal {
>>   constructor(){
>> this.done = 0
>>   }
>>   doIt(){
>> this.done++
>>   }
>> }
>> class Cat extends Animal {}
>> class Dog extends Animal {}
>> class Dog1 extends Animal {}
>> class Dog2 extends Animal {}
>> class Dog3 extends Animal {}
>>
>> function test(){
>>   var cat = new Cat();
>>   cat.doIt();
>>   cat.doIt();
>>   cat.doIt();
>>   var dog = new Dog();
>>   dog.doIt();
>>   dog.doIt();
>>   dog.doIt();
>>   var dog1 = new Dog1();
>>   dog1.doIt();
>>   dog1.doIt();
>>   dog1.doIt();
>>   var dog2 = new Dog2();
>>   dog2.doIt();
>>   dog2.doIt();
>>   dog2.doIt();
>>   var dog3 = new Dog3();
>>   dog3.doIt();
>>   dog3.doIt();
>>   dog3.doIt();
>>   %OptimizeFunctionOnNextCall(dog3.doIt)
>>   dog3.doIt()
>> }
>> test()
>>
>> I got this output:
>>
>> 0x2df967b05180 0  55 push rbp
>> 0x2df967b05181 1  4889e5 REX.W movq rbp,rsp
>> 0x2df967b05184 4  56 push rsi
>> 0x2df967b05185 5  57 push rdi
>> 0x2df967b05186 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
>> 0x2df967b0518d d  0f866900   jna 0x2df967b051fc  <+0x7c>
>> 0x2df967b0519313  488b75f8   REX.W movq rsi,[rbp-0x8]
>> 0x2df967b0519717  48b80300 REX.W movq rax,0x3
>> 0x2df967b051a121  488b5510   REX.W movq rdx,[rbp+0x10]
>> 0x2df967b051a525  498b8dd005 REX.W movq rcx,[r13+0x5d0]
>> 0x2df967b051ac2c  488bd9 REX.W movq rbx,rcx
>> 0x2df967b051af2f  e8ccd7f4ff call 0x2df967a52980
>> (LoadICTrampoline);; code: LOAD_IC
>> 0x2df967b051b434  a801   test al,0x1
>> 0x2df967b051b636  0f855700   jnz 0x2df967b05213  <+0x93>
>> 0x2df967b051bc3c  488bd8 REX.W movq rbx,rax
>> 0x2df967b051bf3f  48c1eb20   REX.W shrq rbx, 32
>> 0x2df967b051c343  83ebff subl rbx,0xff
>> 0x2df967b051c646  0f804c00   jo 0x2df967b05218  <+0x98>
>> 0x2df967b051cc4c  48c1e320   REX.W shlq rbx, 32
>> 0x2df967b051d050  48bf0500 REX.W movq rdi,0x5
>> 

[v8-users] Re: Interceptor gets called only once on an instance

2017-09-24 Thread Zac Hansen
I'd suggest implementing the other parts of the interceptor and see if 
they're getting called.. and if so, make sure to implement them properly 
for your object.

This is just the approach I would take without really understanding why 
you're seeing this behavior..

On Friday, September 22, 2017 at 4:41:59 AM UTC-7, Alexandre Parenteau 
wrote:
>
> Hi,
>
> Using V8 5.1.
>
> I have this function template class "Group":
>
> templ->SetClassName(v8::String::NewFromUtf8(isolateP, "Group"));
>
>   v8::Handle inst = templ->InstanceTemplate();
> inst->SetInternalFieldCount(1);
>
> I set an accessor "foo", and this one gets always called when doing 
> "group.foo":
>
> inst->SetAccessor(v8::String::NewFromUtf8(isolateP,* "foo"*), 
> getProperty, 0, v8::Int32::New(42));
>
> The interceptor intercepts "bar". GroupNamedQueryInterceptor returns 
> "v8::PropertyAttribute::None" for "bar"
>
> inst->SetHandler(v8::NamedPropertyHandlerConfiguration(
> *GroupNamedPropertyGetter*, NULL, *GroupNamedQueryInterceptor*, NULL, 
> NULL,
> v8::Local(),
> v8::PropertyHandlerFlags(0)));
>
> The initial instance is created with:
>
> v8::Handle instance = ...>GetFunction()->NewInstance();
>
> And added to the global scope as "group" of class "Group"
>
> When executing "group.bar", I get in the interceptor 
> *GroupNamedQueryInterceptor*. The getter *GroupNamedPropertyGetter* creates 
> a *new instance* of same class "Group", and returns it.
>
> So now "bar" is an instance of "Group" as well.
>
> So I would expect "group.bar.bar" to come back in the interceptor a second 
> time, but it does not!
>
> However "group.bar.foo" accesses the second instance accessor just fine.
>
> It feels really strange. I was hoping someone could unstuck me.
>
> Thanks in advance!
> alex
>
>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [v8-users] Re: Is "extend" keyword a performance antipattern???

2017-09-24 Thread Caitlin Potter
So yes, the load/store for `this.done++` can't be reduced to simple machine 
ops when `doIt` is megamorphic, as far as I can tell. (5+ receiver maps 
should make the load/stores megamorphic, or at least that's what 
https://github.com/v8/v8/blob/9a0d5d9700ee269cbe7abee6d62733163dadac14/src/ic/ic.h#L33-L35
 
seems to indicate).

That doesn't necessarily mean LoadIC is going to be slow, I guess it 
depends on how often you the receiver map is missing from the cache. Slower 
than the inlined monomorphic in-object field load/store, but probably not 
"anti-pattern" slow.

I could be wrong about this, but I think the CallIC for individual calls to 
`doIt` can be inlined with different type feedback information for the 
load/store, so if that shows up in hot code which is monomorphic or 
polymorphic, it might produce better code than your example there.

That said, I'm half guessing about all of this, so I'll leave the rest of 
this thread for more knowledgeable people.

On Sunday, September 24, 2017 at 12:07:58 PM UTC-4, Bogdan Orlov wrote:
>
> After removing all intermediate %OptimizeFunctionOnNextCall()  and putting 
> at the end (after usage of all Animal subclasses for enough feedback) like 
> this
>
> class Animal {
>   constructor(){
> this.done = 0
>   }
>   doIt(){
> this.done++
>   }
> }
> class Cat extends Animal {}
> class Dog extends Animal {}
> class Dog1 extends Animal {}
> class Dog2 extends Animal {}
> class Dog3 extends Animal {}
>
> function test(){
>   var cat = new Cat();
>   cat.doIt();
>   cat.doIt();
>   cat.doIt();
>   var dog = new Dog();
>   dog.doIt();
>   dog.doIt();
>   dog.doIt();
>   var dog1 = new Dog1();
>   dog1.doIt();
>   dog1.doIt();
>   dog1.doIt();
>   var dog2 = new Dog2();
>   dog2.doIt();
>   dog2.doIt();
>   dog2.doIt();
>   var dog3 = new Dog3();
>   dog3.doIt();
>   dog3.doIt();
>   dog3.doIt();
>   %OptimizeFunctionOnNextCall(dog3.doIt)
>   dog3.doIt()
> }
> test()
>
> I got this output:
>
> 0x2df967b05180 0  55 push rbp
> 0x2df967b05181 1  4889e5 REX.W movq rbp,rsp
> 0x2df967b05184 4  56 push rsi
> 0x2df967b05185 5  57 push rdi
> 0x2df967b05186 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
> 0x2df967b0518d d  0f866900   jna 0x2df967b051fc  <+0x7c>
> 0x2df967b0519313  488b75f8   REX.W movq rsi,[rbp-0x8]
> 0x2df967b0519717  48b80300 REX.W movq rax,0x3
> 0x2df967b051a121  488b5510   REX.W movq rdx,[rbp+0x10]
> 0x2df967b051a525  498b8dd005 REX.W movq rcx,[r13+0x5d0]
> 0x2df967b051ac2c  488bd9 REX.W movq rbx,rcx
> 0x2df967b051af2f  e8ccd7f4ff call 0x2df967a52980  
> (LoadICTrampoline);; code: LOAD_IC
> 0x2df967b051b434  a801   test al,0x1
> 0x2df967b051b636  0f855700   jnz 0x2df967b05213  <+0x93>
> 0x2df967b051bc3c  488bd8 REX.W movq rbx,rax
> 0x2df967b051bf3f  48c1eb20   REX.W shrq rbx, 32
> 0x2df967b051c343  83ebff subl rbx,0xff
> 0x2df967b051c646  0f804c00   jo 0x2df967b05218  <+0x98>
> 0x2df967b051cc4c  48c1e320   REX.W shlq rbx, 32
> 0x2df967b051d050  48bf0500 REX.W movq rdi,0x5
> 0x2df967b051da5a  488b5510   REX.W movq rdx,[rbp+0x10]
> 0x2df967b051de5e  498b8dd005 REX.W movq rcx,[r13+0x5d0]
> 0x2df967b051e565  488bc3 REX.W movq rax,rbx
> 0x2df967b051e868  488b75f8   REX.W movq rsi,[rbp-0x8]
> 0x2df967b051ec6c  e8cf1ff5ff call 0x2df967a571c0  
> (StoreICStrictTrampoline);; code: STORE_IC
> 0x2df967b051f171  498b45a0   REX.W movq rax,[r13-0x60]
> 0x2df967b051f575  488be5 REX.W movq rsp,rbp
> 0x2df967b051f878  5d pop rbp
> 0x2df967b051f979  c20800 ret 0x8
> 0x2df967b051fc7c  48bbe07c89000100 REX.W movq rbx,0x100897ce0
> 0x2df967b0520686  33c0   xorl rax,rax
> 0x2df967b0520888  488b75f8   REX.W movq rsi,[rbp-0x8]
> 0x2df967b0520c8c  e88ff4e7ff call 0x2df9679846a0 ;; code: 
> STUB, CEntryStub, minor: 8
> 0x2df967b0521191  eb80   jmp 0x2df967b05193  <+0x13>
> 0x2df967b0521393  e8fcedcfff call 0x2df967804014 ;; debug: 
> deopt position, script offset '130'
>  ;; debug: 
> deopt position, inlining id '-1'
>  ;; debug: 
> deopt reason 'not a Smi'
>  ;; debug: 
> deopt index 2
>  ;; 
> deoptimization bailout 2
> 0x2df967b0521898  e801eecfff call 0x2df96780401e ;; debug: 
> deopt position, script offset '130'
>  ;; debug: 
> deopt position, inlining id '-1'
>  ;; debug: 
> deopt reason 'overflow'
>  

Re: [v8-users] Re: Is "extend" keyword a performance antipattern???

2017-09-24 Thread B. Orlov
After removing all intermediate %OptimizeFunctionOnNextCall()  and putting 
at the end (after usage of all Animal subclasses for enough feedback) like 
this

class Animal {
  constructor(){
this.done = 0
  }
  doIt(){
this.done++
  }
}
class Cat extends Animal {}
class Dog extends Animal {}
class Dog1 extends Animal {}
class Dog2 extends Animal {}
class Dog3 extends Animal {}

function test(){
  var cat = new Cat();
  cat.doIt();
  cat.doIt();
  cat.doIt();
  var dog = new Dog();
  dog.doIt();
  dog.doIt();
  dog.doIt();
  var dog1 = new Dog1();
  dog1.doIt();
  dog1.doIt();
  dog1.doIt();
  var dog2 = new Dog2();
  dog2.doIt();
  dog2.doIt();
  dog2.doIt();
  var dog3 = new Dog3();
  dog3.doIt();
  dog3.doIt();
  dog3.doIt();
  %OptimizeFunctionOnNextCall(dog3.doIt)
  dog3.doIt()
}
test()

I got this output:

0x2df967b05180 0  55 push rbp
0x2df967b05181 1  4889e5 REX.W movq rbp,rsp
0x2df967b05184 4  56 push rsi
0x2df967b05185 5  57 push rdi
0x2df967b05186 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
0x2df967b0518d d  0f866900   jna 0x2df967b051fc  <+0x7c>
0x2df967b0519313  488b75f8   REX.W movq rsi,[rbp-0x8]
0x2df967b0519717  48b80300 REX.W movq rax,0x3
0x2df967b051a121  488b5510   REX.W movq rdx,[rbp+0x10]
0x2df967b051a525  498b8dd005 REX.W movq rcx,[r13+0x5d0]
0x2df967b051ac2c  488bd9 REX.W movq rbx,rcx
0x2df967b051af2f  e8ccd7f4ff call 0x2df967a52980  
(LoadICTrampoline);; code: LOAD_IC
0x2df967b051b434  a801   test al,0x1
0x2df967b051b636  0f855700   jnz 0x2df967b05213  <+0x93>
0x2df967b051bc3c  488bd8 REX.W movq rbx,rax
0x2df967b051bf3f  48c1eb20   REX.W shrq rbx, 32
0x2df967b051c343  83ebff subl rbx,0xff
0x2df967b051c646  0f804c00   jo 0x2df967b05218  <+0x98>
0x2df967b051cc4c  48c1e320   REX.W shlq rbx, 32
0x2df967b051d050  48bf0500 REX.W movq rdi,0x5
0x2df967b051da5a  488b5510   REX.W movq rdx,[rbp+0x10]
0x2df967b051de5e  498b8dd005 REX.W movq rcx,[r13+0x5d0]
0x2df967b051e565  488bc3 REX.W movq rax,rbx
0x2df967b051e868  488b75f8   REX.W movq rsi,[rbp-0x8]
0x2df967b051ec6c  e8cf1ff5ff call 0x2df967a571c0  
(StoreICStrictTrampoline);; code: STORE_IC
0x2df967b051f171  498b45a0   REX.W movq rax,[r13-0x60]
0x2df967b051f575  488be5 REX.W movq rsp,rbp
0x2df967b051f878  5d pop rbp
0x2df967b051f979  c20800 ret 0x8
0x2df967b051fc7c  48bbe07c89000100 REX.W movq rbx,0x100897ce0
0x2df967b0520686  33c0   xorl rax,rax
0x2df967b0520888  488b75f8   REX.W movq rsi,[rbp-0x8]
0x2df967b0520c8c  e88ff4e7ff call 0x2df9679846a0 ;; code: STUB, 
CEntryStub, minor: 8
0x2df967b0521191  eb80   jmp 0x2df967b05193  <+0x13>
0x2df967b0521393  e8fcedcfff call 0x2df967804014 ;; debug: 
deopt position, script offset '130'
 ;; debug: 
deopt position, inlining id '-1'
 ;; debug: 
deopt reason 'not a Smi'
 ;; debug: 
deopt index 2
 ;; 
deoptimization bailout 2
0x2df967b0521898  e801eecfff call 0x2df96780401e ;; debug: 
deopt position, script offset '130'
 ;; debug: 
deopt position, inlining id '-1'
 ;; debug: 
deopt reason 'overflow'
 ;; debug: 
deopt index 3
 ;; 
deoptimization bailout 3
0x2df967b0521d9d  90 nop
0x2df967b0521e9e  90 nop
0x2df967b0521f9f  90 nop
0x2df967b05220a0  90 nop
0x2df967b05221a1  90 nop
0x2df967b05222a2  90 nop
0x2df967b05223a3  90 nop
0x2df967b05224a4  90 nop
0x2df967b05225a5  90 nop
0x2df967b05226a6  90 nop
0x2df967b05227a7  90 nop
0x2df967b05228a8  90 nop
0x2df967b05229a9  90 nop
0x2df967b0522aaa  6690   nop

So the result is the same (but without intermediate deopts) - v8 compiles 
'this.done++' to slow polymorphic runtime calls LoadICTrampoline and 
StoreICStrictTrampoline. And if this is not a bug and v8 just works this 
way, we have slow polymorphic accessing to 'this' object in all base class 
methods in commonly used inheritance and polymorphism pattern and thus 
'extends' keyword come out as performance antipattern


On Sunday, September 24, 2017 at 4:31:44 PM UTC+3, Caitlin Potter wrote:
>
> I think 

Re: [v8-users] Re: Is "extend" keyword a performance antipattern???

2017-09-24 Thread Caitlin Potter
I think %OptimizeFunctionOnNextCall() is particularly bad for benchmarks, 
because you train the function to think the method load is monomorphic.

With more type feedback, this should do a bit better, I think we can inline a 
finite amount of polymorphic loads.

At least, I _think_ so.

> On Sep 24, 2017, at 3:12 AM, B. Orlov  wrote:
> 
> Ok, there is more details. This is simplified example without loops 
> 
> class Animal {
>   constructor(){
> this.done = 0
>   }
>   doIt(){
> this.done++
>   }
> }
> 
> class Cat extends Animal {}
> 
> class Dog extends Animal {}
> class Dog1 extends Animal {}
> class Dog2 extends Animal {}
> class Dog3 extends Animal {}
> 
> class AnimalCat {
>   constructor(){
> this.done = 0
>   }
>   doIt(){
> this.done++
>   }
> }
> 
> function test(){
>   var cat = new Cat();
>   cat.doIt();
>   cat.doIt(); //warm
>   %OptimizeFunctionOnNextCall(cat.doIt)
>   cat.doIt(); //fast REX.W asm instruction for this.done read and write
> 
>   var dog = new Dog();
>   dog.doIt(); //deopt - wrong map
>   %OptimizeFunctionOnNextCall(dog.doIt)
>   dog.doIt(); //the same but now added check for new hidden map - Dog
> 
>   var dog1 = new Dog1();
>   dog1.doIt(); //deopt - wrong map
>   %OptimizeFunctionOnNextCall(dog1.doIt)
>   dog1.doIt() //the same but now added one more check for new hidden map - 
> Dog1
> 
>   var dog2 = new Dog2();
>   dog2.doIt(); //deopt - wrong map
>   %OptimizeFunctionOnNextCall(dog2.doIt)
>   dog2.doIt() //the same but now added one more check for new hidden map - 
> Dog2
> 
>   var dog3 = new Dog3();
>   dog3.doIt(); //deopt - wrong map
>   %OptimizeFunctionOnNextCall(dog3.doIt)
>   dog3.doIt() //v8 gives up and compiles this.done to slow calls c++ runtime 
> functions - LoadICTrampoline and StoreICStrictTrampoline
> }
> 
> test()
> 
> Running with latest node with arguments "node --trace-deopt --print-opt-code 
> --allow-natives-syntax test.js" there will be output of asm instructions for 
> each optimization of doIt() method. After first optimizations (with only Cat 
> class invoking) I got
> 
> 0x3e9869385180 0  55 push rbp
> 0x3e9869385181 1  4889e5 REX.W movq rbp,rsp
> 0x3e9869385184 4  56 push rsi
> 0x3e9869385185 5  57 push rdi
> 0x3e9869385186 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
> 0x3e986938518d d  0f863f00   jna 0x3e98693851d2  <+0x52>
> 0x3e986938519313  488b4510   REX.W movq rax,[rbp+0x10]
> 0x3e986938519717  a801   test al,0x1
> 0x3e986938519919  0f844a00   jz 0x3e98693851e9  <+0x69>
> 0x3e986938519f1f  48bb9112642f9b32 REX.W movq rbx,0x329b2f641291
> ;; object: 0x329b2f641291 
> 0x3e98693851a929  483958ff   REX.W cmpq [rax-0x1],rbx
> 0x3e98693851ad2d  0f853b00   jnz 0x3e98693851ee  <+0x6e>
> 0x3e98693851b333  8b581b movl rbx,[rax+0x1b]
> 0x3e98693851b636  83ebff subl rbx,0xff
> 0x3e98693851b939  0f803400   jo 0x3e98693851f3  <+0x73>
> 0x3e98693851bf3f  48c1e320   REX.W shlq rbx, 32
> 0x3e98693851c343  48895817   REX.W movq [rax+0x17],rbx
> 0x3e98693851c747  498b45a0   REX.W movq rax,[r13-0x60]
> 0x3e98693851cb4b  488be5 REX.W movq rsp,rbp
> 0x3e98693851ce4e  5d pop rbp
> 0x3e98693851cf4f  c20800 ret 0x8
> 
> than after few deoptimizations for Dog2 class V8 compiles doIt() method to 
> this
> 
> 0x3e9869385540 0  55 push rbp
> 0x3e9869385541 1  4889e5 REX.W movq rbp,rsp
> 0x3e9869385544 4  56 push rsi
> 0x3e9869385545 5  57 push rdi
> 0x3e9869385546 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
> 0x3e986938554d d  0f867b00   jna 0x3e98693855ce  <+0x8e>
> 0x3e986938555313  488b4510   REX.W movq rax,[rbp+0x10]
> 0x3e986938555717  a801   test al,0x1
> 0x3e986938555919  0f848900   jz 0x3e98693855e8  <+0xa8>
> 0x3e986938555f1f  488b58ff   REX.W movq rbx,[rax-0x1]
> 0x3e986938556323  48ba9112642f9b32 REX.W movq rdx,0x329b2f641291
> ;; object: 0x329b2f641291 
> 0x3e986938556d2d  483bd3 REX.W cmpq rdx,rbx
> 0x3e986938557030  0f843900   jz 0x3e98693855af  <+0x6f>
> 0x3e986938557636  48ba4914642f9b32 REX.W movq rdx,0x329b2f641449
> ;; object: 0x329b2f641449 
> 0x3e986938558040  483bd3 REX.W cmpq rdx,rbx
> 0x3e986938558343  0f842600   jz 0x3e98693855af  <+0x6f>
> 0x3e986938558949  48ba5115642f9b32 REX.W movq rdx,0x329b2f641551
> ;; object: 0x329b2f641551 
> 0x3e986938559353  483bd3 REX.W cmpq rdx,rbx
> 0x3e986938559656  0f841300   jz 0x3e98693855af  <+0x6f>
> 0x3e986938559c5c  48ba5916642f9b32 REX.W movq rdx,0x329b2f641659
> ;; object: 0x329b2f641659 
> 

[v8-users] Re: Is "extend" keyword a performance antipattern???

2017-09-24 Thread B. Orlov
Ok, there is more details. This is simplified example without loops 

class Animal {
  constructor(){
this.done = 0
  }
  doIt(){
this.done++
  }
}

class Cat extends Animal {}

class Dog extends Animal {}
class Dog1 extends Animal {}
class Dog2 extends Animal {}
class Dog3 extends Animal {}

class AnimalCat {
  constructor(){
this.done = 0
  }
  doIt(){
this.done++
  }
}

function test(){
  var cat = new Cat();
  cat.doIt();
  cat.doIt(); //warm
  %OptimizeFunctionOnNextCall(cat.doIt)
  cat.doIt(); //fast REX.W asm instruction for this.done read and write

  var dog = new Dog();
  dog.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog.doIt)
  dog.doIt(); //the same but now added check for new hidden map - Dog

  var dog1 = new Dog1();
  dog1.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog1.doIt)
  dog1.doIt() //the same but now added one more check for new hidden map - 
Dog1

  var dog2 = new Dog2();
  dog2.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog2.doIt)
  dog2.doIt() //the same but now added one more check for new hidden map - 
Dog2

  var dog3 = new Dog3();
  dog3.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog3.doIt)
  dog3.doIt() //v8 gives up and compiles this.done to slow calls c++ 
runtime functions - LoadICTrampoline and StoreICStrictTrampoline
}

test()

Running with latest node with arguments "node --trace-deopt 
--print-opt-code --allow-natives-syntax test.js" there will be output of 
asm instructions for each optimization of doIt() method. After first 
optimizations (with only Cat class invoking) I got

0x3e9869385180 0  55 push rbp
0x3e9869385181 1  4889e5 REX.W movq rbp,rsp
0x3e9869385184 4  56 push rsi
0x3e9869385185 5  57 push rdi
0x3e9869385186 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
0x3e986938518d d  0f863f00   jna 0x3e98693851d2  <+0x52>
0x3e986938519313  488b4510   REX.W movq rax,[rbp+0x10]
0x3e986938519717  a801   test al,0x1
0x3e986938519919  0f844a00   jz 0x3e98693851e9  <+0x69>
0x3e986938519f1f  48bb9112642f9b32 REX.W movq rbx,0x329b2f641291
;; object: 0x329b2f641291 
0x3e98693851a929  483958ff   REX.W cmpq [rax-0x1],rbx
0x3e98693851ad2d  0f853b00   jnz 0x3e98693851ee  <+0x6e>
0x3e98693851b333  8b581b movl rbx,[rax+0x1b]
0x3e98693851b636  83ebff subl rbx,0xff
0x3e98693851b939  0f803400   jo 0x3e98693851f3  <+0x73>
0x3e98693851bf3f  48c1e320   REX.W shlq rbx, 32
0x3e98693851c343  48895817   REX.W movq [rax+0x17],rbx
0x3e98693851c747  498b45a0   REX.W movq rax,[r13-0x60]
0x3e98693851cb4b  488be5 REX.W movq rsp,rbp
0x3e98693851ce4e  5d pop rbp
0x3e98693851cf4f  c20800 ret 0x8

than after few deoptimizations for Dog2 class V8 compiles doIt() method to 
this

0x3e9869385540 0  55 push rbp
0x3e9869385541 1  4889e5 REX.W movq rbp,rsp
0x3e9869385544 4  56 push rsi
0x3e9869385545 5  57 push rdi
0x3e9869385546 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
0x3e986938554d d  0f867b00   jna 0x3e98693855ce  <+0x8e>
0x3e986938555313  488b4510   REX.W movq rax,[rbp+0x10]
0x3e986938555717  a801   test al,0x1
0x3e986938555919  0f848900   jz 0x3e98693855e8  <+0xa8>
0x3e986938555f1f  488b58ff   REX.W movq rbx,[rax-0x1]
0x3e986938556323  48ba9112642f9b32 REX.W movq rdx,0x329b2f641291
;; object: 0x329b2f641291 
0x3e986938556d2d  483bd3 REX.W cmpq rdx,rbx
0x3e986938557030  0f843900   jz 0x3e98693855af  <+0x6f>
0x3e986938557636  48ba4914642f9b32 REX.W movq rdx,0x329b2f641449
;; object: 0x329b2f641449 
0x3e986938558040  483bd3 REX.W cmpq rdx,rbx
0x3e986938558343  0f842600   jz 0x3e98693855af  <+0x6f>
0x3e986938558949  48ba5115642f9b32 REX.W movq rdx,0x329b2f641551
;; object: 0x329b2f641551 
0x3e986938559353  483bd3 REX.W cmpq rdx,rbx
0x3e986938559656  0f841300   jz 0x3e98693855af  <+0x6f>
0x3e986938559c5c  48ba5916642f9b32 REX.W movq rdx,0x329b2f641659
;; object: 0x329b2f641659 
0x3e98693855a666  483bd3 REX.W cmpq rdx,rbx
0x3e98693855a969  0f853e00   jnz 0x3e98693855ed  <+0xad>
0x3e98693855af6f  8b581b movl rbx,[rax+0x1b]
0x3e98693855b272  83ebff subl rbx,0xff
0x3e98693855b575  0f803700   jo 0x3e98693855f2  <+0xb2>
0x3e98693855bb7b  48c1e320   REX.W shlq rbx, 32
0x3e98693855bf7f  48895817   REX.W movq [rax+0x17],rbx
0x3e98693855c383  498b45a0   REX.W movq rax,[r13-0x60]
0x3e98693855c787  488be5 REX.W movq rsp,rbp
0x3e98693855ca8a  5d pop rbp
0x3e98693855cb8b  

[v8-users] Re: Is "extend" keyword a performance antipattern???

2017-09-24 Thread B. Orlov
Ok, I there is more details. This is simplified example without loops 

class Animal {
  constructor(){
this.done = 0
  }
  doIt(){
this.done++
  }
}

class Cat extends Animal {}

class Dog extends Animal {}
class Dog1 extends Animal {}
class Dog2 extends Animal {}
class Dog3 extends Animal {}

class AnimalCat {
  constructor(){
this.done = 0
  }
  doIt(){
this.done++
  }
}

function test(){
  var cat = new Cat();
  cat.doIt();
  cat.doIt(); //warm
  %OptimizeFunctionOnNextCall(cat.doIt)
  cat.doIt(); //fast REX.W asm instruction for this.done read and write

  var dog = new Dog();
  dog.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog.doIt)
  dog.doIt(); //the same but now added check for new hidden map - Dog

  var dog1 = new Dog1();
  dog1.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog1.doIt)
  dog1.doIt() //the same but now added one more check for new hidden map - 
Dog1

  var dog2 = new Dog2();
  dog2.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog2.doIt)
  dog2.doIt() //the same but now added one more check for new hidden map - 
Dog2

  var dog3 = new Dog3();
  dog3.doIt(); //deopt - wrong map
  %OptimizeFunctionOnNextCall(dog3.doIt)
  dog3.doIt() //v8 gives up and compiles this.done to slow calls c++ 
runtime functions - LoadICTrampoline and StoreICStrictTrampoline
}

test()

Running with latest node with arguments "node --trace-deopt 
--print-opt-code --allow-natives-syntax test.js" there will be output of 
asm instructions for each optimization of doIt() method. After first 
optimizations (with only Cat class invoking) I got

0x3e9869385180 0  55 push rbp
0x3e9869385181 1  4889e5 REX.W movq rbp,rsp
0x3e9869385184 4  56 push rsi
0x3e9869385185 5  57 push rdi
0x3e9869385186 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
0x3e986938518d d  0f863f00   jna 0x3e98693851d2  <+0x52>
0x3e986938519313  488b4510   REX.W movq rax,[rbp+0x10]
0x3e986938519717  a801   test al,0x1
0x3e986938519919  0f844a00   jz 0x3e98693851e9  <+0x69>
0x3e986938519f1f  48bb9112642f9b32 REX.W movq rbx,0x329b2f641291
;; object: 0x329b2f641291 
0x3e98693851a929  483958ff   REX.W cmpq [rax-0x1],rbx
0x3e98693851ad2d  0f853b00   jnz 0x3e98693851ee  <+0x6e>
0x3e98693851b333  8b581b movl rbx,[rax+0x1b]
0x3e98693851b636  83ebff subl rbx,0xff
0x3e98693851b939  0f803400   jo 0x3e98693851f3  <+0x73>
0x3e98693851bf3f  48c1e320   REX.W shlq rbx, 32
0x3e98693851c343  48895817   REX.W movq [rax+0x17],rbx
0x3e98693851c747  498b45a0   REX.W movq rax,[r13-0x60]
0x3e98693851cb4b  488be5 REX.W movq rsp,rbp
0x3e98693851ce4e  5d pop rbp
0x3e98693851cf4f  c20800 ret 0x8

than after few deoptimizations for Dog2 class V8 compiles doIt() method to 
this

0x3e9869385540 0  55 push rbp
0x3e9869385541 1  4889e5 REX.W movq rbp,rsp
0x3e9869385544 4  56 push rsi
0x3e9869385545 5  57 push rdi
0x3e9869385546 6  493ba5480c REX.W cmpq rsp,[r13+0xc48]
0x3e986938554d d  0f867b00   jna 0x3e98693855ce  <+0x8e>
0x3e986938555313  488b4510   REX.W movq rax,[rbp+0x10]
0x3e986938555717  a801   test al,0x1
0x3e986938555919  0f848900   jz 0x3e98693855e8  <+0xa8>
0x3e986938555f1f  488b58ff   REX.W movq rbx,[rax-0x1]
0x3e986938556323  48ba9112642f9b32 REX.W movq rdx,0x329b2f641291
;; object: 0x329b2f641291 
0x3e986938556d2d  483bd3 REX.W cmpq rdx,rbx
0x3e986938557030  0f843900   jz 0x3e98693855af  <+0x6f>
0x3e986938557636  48ba4914642f9b32 REX.W movq rdx,0x329b2f641449
;; object: 0x329b2f641449 
0x3e986938558040  483bd3 REX.W cmpq rdx,rbx
0x3e986938558343  0f842600   jz 0x3e98693855af  <+0x6f>
0x3e986938558949  48ba5115642f9b32 REX.W movq rdx,0x329b2f641551
;; object: 0x329b2f641551 
0x3e986938559353  483bd3 REX.W cmpq rdx,rbx
0x3e986938559656  0f841300   jz 0x3e98693855af  <+0x6f>
0x3e986938559c5c  48ba5916642f9b32 REX.W movq rdx,0x329b2f641659
;; object: 0x329b2f641659 
0x3e98693855a666  483bd3 REX.W cmpq rdx,rbx
0x3e98693855a969  0f853e00   jnz 0x3e98693855ed  <+0xad>
0x3e98693855af6f  8b581b movl rbx,[rax+0x1b]
0x3e98693855b272  83ebff subl rbx,0xff
0x3e98693855b575  0f803700   jo 0x3e98693855f2  <+0xb2>
0x3e98693855bb7b  48c1e320   REX.W shlq rbx, 32
0x3e98693855bf7f  48895817   REX.W movq [rax+0x17],rbx
0x3e98693855c383  498b45a0   REX.W movq rax,[r13-0x60]
0x3e98693855c787  488be5 REX.W movq rsp,rbp
0x3e98693855ca8a  5d pop rbp
0x3e98693855cb8b