How does V8 manage the memory of object instances? - v8

http://code.google.com/apis/v8/design.html
The above page explains the optimization technique v8 team uses to enable fast property access.
But how about it's object instances? New properties can be added to the object anytime, so it should be allowed to grow in size. Does it simply allocate the memory with a default size and when it hits the size limit creates a new buffer and copy the old instance to the new buffer? Or there's another cool trick?

Newly allocated JavaScript object in V8 look like (-> means "points to"):
[ class ] -> ... ; pointer to the hidden class
[ properties ] -> [empty array]
[ elements ] -> [empty array] ; elements are properties with numeric names
[ reserved #1 ] -\
[ reserved #2 ] |
[ reserved #3 ] }- space reserved for "in object properties"
............... |
[ reserved #N ] -/
There is a certain space in every object pre-allocated for so called in object properties. Number of pre-allocated properties is chosen by V8 depending on the constructor (e.g. number of assignments of the form this.field = expr) and runtime profiling.
When you add a new property to an object V8 first tries to put into pre-allocated in-object slot. When in-object slots are exhausted V8 starts putting them into out-of-object properties array. The mapping between property names and property indexes is stored in the hidden class. For example JS object { a: 1, b: 2, c: 3, d: 4} might look like:
[ class ] -> [a: in obj #1, b: in obj #2, c: out obj #1, d: out obj #2]
[ properties ] -> [ 3 ][ 4 ] ; this is linear array
[ elements ]
[ 1 ]
[ 2 ]
If properties array grows too big V8 will normalize an object: convert it's properties to a dictionary form:
[ class ] -> [ OBJECT IS IN DICTIONARY MODE ]
[ properties ] -> [a: 1, b: 2, c: 3, d: 4, e: 5] ; this is classical hash table
[ elements ]

Related

Initializing a matrix using a list with a string in it

Here is my code:
extensions [matrix]
..
sources-own[keyword1 keyword2 keyword3 keyword4 extrinsic-fitness visits]
..
to setup
create-sources
ask source 0 [
set keyword1 (matrix:from-row-list [["cat"][2]])
]
...
..
.
Now, when I click on SETUP and inspect "source 0", it shows the matrix to be initialized as the following:
{{matrix: [ [ 0 ][ 2 ] ]}}
Try as I might, I cannot get it to accept the string "cat" in place of the "0" in the first column.
OK, I got it.
A matrix in Netlogo can only hold numbers. One needs to use a "list" instead.

Stretching words and quotation scoping

To play at Stretch the word, I've defined the following words, to try to work at the problem via the same method as this answer:
USING: kernel math sequences sequences.repeating ;
IN: stretch-words
! "bonobo" -> { "b" "bo" "bon" "bono" "bonob" "bonobo" }
: ascend-string ( string -- ascending-seqs )
dup length 1 + iota [ 0 swap pick subseq ] map
[ "" = not ] filter nip ;
! expected: "bonobo" -> "bonoobbooo"
! actual: "bonobo" -> "bbbooonnnooobbbooo"
: stretch-word ( string -- stretched )
dup ascend-string swap zip
[
dup first swap last
[ = ] curry [ dup ] dip count
repeat
] map last ;
stretch-word is supposed to repeat a character in a string by the number of times it's appeared up to that position in the string. However, my implementation is repeating all instances of the 1string it gets.
I have the feeling this is easily implementable in Factor, but I can't quite figure it out. How do I make this do what I want?
Hm... not a great golf, but it works...
First, I made a minor change to ascend-string so it leaves the string on the stack:
: ascend-string ( string -- string ascending-seqs )
dup length 1 + iota [ 0 swap pick subseq ] map
[ "" = not ] filter ;
So stretch-word can work like this:
: stretch-word ( string -- stretched )
ascend-string zip ! just zip them in the same order
[
first2 over ! first2 is the only golf I could make :/
[ = ] curry count ! same thing
swap <array> >string ! make an array of char size count and make it a string
] map concat ; ! so you have to join the pieces
Edit:
I think the problem was using repeat to do the job.
: ascend-string ( string -- seqs )
"" [ suffix ] { } accumulate*-as ;
: counts ( string -- counts )
dup ascend-string [ indices length ] { } 2map-as ;
: stretch-word ( string -- stretched )
[ counts ] keep [ <string> ] { } 2map-as concat ;
"bonobo" stretch-word print
bonoobbooo
indices length could also be [ = ] with count

Dynamic layout additions in Rebol3

I would like to dynamically add a button to the layout of a view, with the actor causing this addition belonging to a button that is already part of the layout.
I started with this:
REBOL [title: "Dynamic Button Addition"]
tilesize: 60x60
curtile: 1
stylize [
p: button [
facets: [init-size: tilesize max-size: tilesize]
actors: [
on-action: [
++ curtile
append tiles compose [ p (to-string curtile) ]
print ? tiles/options/content
v/redraw
]
]
]
]
v: [
tiles: hgroup [ p "1" ]
]
view v
...which does not appear to have the value of tiles/options/content change with each click.
I can get it to change if make these changes:
append tiledata compose [ p (to-string curtile) ]
and
tiledata: [ p "1" ]
v: [
tiles: hgroup tiledata
However, this does not cause any change on screen. If I replace the last four lines with this:
v: view [
tiles: hgroup tiledata
]
...so that v is now the view rather than the view's layout, I get this error when I click:
** Script error: v has no value
** Where: actor all foreach do-actor unless do-face if actor all foreach do-actor if do-event do-event if do-event either -apply- wake-up loop -apply- wait forever try do-events if view do either either either -apply-
** Near: actor face :data
This makes sense to me, because v is not yet done being defined, until I exit the program, IIUC.
How, then, can I make changes to v before the program ends, but after it's been passed to view?
Not very nice, but working if you replace
v/redraw
with these two lines
unview/all
view v
And there is a real dynamic example on how to update a layout that has already be viewed
I will simplify it
stylize [
tbox: hpanel [
actors: [
on-make: [
append face/options [
content: [
]
]
do-actor/style face 'on-make none 'hpanel
]
]
]
]
view/across [
button "button 1"
on-action [
append-content test compose [
button ( join "button " 2 + length? test/gob)
]
]
test: tbox
]

Evaluating code blocks in Rebol3

I'm trying to improve the Sliding Tile Puzzle example by making the starting positions random.
There's a better way to do this--"It is considered bad practice to convert values to strings and join them together to pass to do for evaluation."--but the approach I took was to try to generate Rebol3 source, and then evaluate it. I have it generating correctly, I think:
random/seed now
arr: random collect [ repeat tilenum 9 [ keep tilenum ] ]
hgroup-data: copy {}
repeat pos 9 [
curtile: (pick arr pos)
append hgroup-data either curtile = 9
[ reduce "x: box tilesize gameback " ]
[ rejoin [ { p "} curtile {" } ] ]
if all [(pos // 3) = 0 pos != 9] [ append hgroup-data " return^/" ]
]
print hgroup-data
...outputs something like:
p "4" x: box tilesize gameback p "5" return
p "3" p "7" p "1" return
p "2" p "8" p "6"
...which if I then copy and paste into this part, works correctly:
view/options [
hgroup [
PASTE-HERE
]
] [bg-color: gameback]
However, if I try to do it dynamically:
view/options [
hgroup [
hgroup-data
]
] [bg-color: gameback]
...(also print hgroup-data, do hgroup-data, and load hgroup-data), I get this error:
** GUI ERROR: Cannot parse the GUI dialect at: hgroup-data
...(or at: print hgroup-data, etc., depending on which variation I tried.)
If I try load [ hgroup-data ] I get:
** Script error: extend-face does not allow none! for its face argument
** Where: either if forever -apply- apply init-layout make-layout actor all foreach do-actor unless -apply- apply all build-face -apply- apply init-layout make-layout actor all foreach do-actor if build-face -apply- apply init-layout make-layout actor all foreach do-actor unless make-face -apply- apply case view do either either either -apply-
** Near: either all [
word? act: dial/1
block? body: get dial...
However, if I use the syntax hgroup do [ hgroup-data ], the program runs, but there are no buttons: it appears to be somehow over-evaluated, so that the return values of the functions p and box and so on are put straight into the hgroup as code.
Surely I'm missing an easy syntax error here. What is it?
First, I would say it's better to construct a block directly, instead of constructing a string and converting it to a block. But if you really want to do that, this should do the trick:
view/options compose/only [
hgroup (load hgroup-data)
] [bg-color: gameback]

Writing an Emulator and need to be able to reference methods/functions in Ruby

I am writing an Emulator in Ruby for a relatively simple 6502 processor.
My question is, is there a way to define a hash or array with details of the assembly instruction, followed by the number of operands it takes, and finally, the method/function that implements it?
Then somewhere in the code, the hash or array can be evaluated based on the instruction read, and the appropriate method/function implemented for it can be launched?
I am open to ideas...
Currently, I have such a structure, but am having difficulties implementing it:
#inst.push [ 0x48, :implied, 1, PHA]
#inst.push [ 0xA2, :immediate, 2, LDX ]
#inst.push [ 0xA9, :immediate, 2, LDA ]
#inst.push [ 0xAD, :absolute, 3, LDA ]
#inst.push [ 0xA6, :zeropage, 2, LDX ]
#inst.push [ 0xB6, :zeropagey, 2, LDX ]
#inst.push [ 0xAE, :absolute, 2, LDX ]
#inst.push [ 0xBE, :absolutey, 2, LDX ]
#inst.push [ 0x8A, :implied, 1, TXA ]
Lambdas, Procs? Can anything like that work for what I am aiming to achieve here?
I really don't want a big "Case/When" for each instruction followed by the statements in one huge, ugly and relatively unfriendly place.
Thanks!
If your instructions are implemented as methods you don't need lambdas. Specify methods using symbols with their names, get actual methods using Class#method and call it using Method#call. What I mean is
method = Object.method :puts
method.call "Oh, it seems to work!"
In your case it would be
implementation = Instructions.method instruction_name
# Store it in a hash in which instruction names are keys or any other
# appropriate data structure. Once you encounter this instruction...
implementation.call
You can use send to call any method on an object
>> a = [1,2,8]
=> [1, 2, 8]
>> a.send(:size)
=> 3
>> a.send(:pop)
=> 8
>> a
=> [1, 2]
>> a.send(:push,42)
=> [1, 2, 42]
so just store the name of the methods which implement your instruction as symbols in the array and then send the symbol to the interpreter to call the associated method.

Resources