spider monkey

Spider Monkey v1.7

 

▣ 명령 프롬프트에서 빌드하기

1. js.mak 내 269 라인에서 “_FIX_JSSHELL” /D 를 추가한다.

/D "WIN32" /D "XP_WIN" /D "JSFILE" /D "_FIX_JSSHELL" /D "EXPORT_JS_API" /Fp"$(INTDIR)/js.pch" /I"$(INTDIR)" /YX\

2.  jsinterp.c 내 _FIX_JSSHELL 조건으로 jsiter.c 를 추가 include 한다.

#include "jsiter.h"

#if _FIX_JSSHELL

#include "jsiter.c"

#endif

3. VS 에서 제공하는 명령 프롬프트를 실행한다.

4. nmake –f js.mak 를 통해 빌드한다. 

 

▣ VC 6.0에서 빌드하기

1. jsautokw.h를 /src/ 아래 위치시킨다.

2. js.mdp 파일을 덮어 씌우고 VC6.0을 통해 open한다.

3. js 프로젝트 내 _FIX_JSSHELL 을 pre define 시킨다.

4. jsutil.h 내 JS_STATIC_ASSERT 정의를 무효화한다.

#define JS_STATIC_ASSERT(condition)                                           \

//    JS_STATIC_ASSERT_IMPL(condition, __LINE__)

5. jsexn.c 내 JS_STATIC_ASSERT 사용을 막는다.

//   JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char *) == 0);

 //   JS_STATIC_ASSERT(sizeof(const char *) % sizeof(jschar) == 0);

6. 빌드한다.

 spicemonkey_v1.7_vc60_build.zip

 

 

▣ JS 1.7이 지원하는 java script 버전은?

1. JS 1.7.0 is based on the same branch (1.8.1.8) as Firefox 2.0.0.8 and includes the same stability and security fixes

-> Firefox 2.0.0.8 버전과 같다고 합니다.

 

2. JavaScript 1.7에 대한 내용을 살펴 보면

 

Version

Release date

Equivalent to

Netscape
Navigator

Mozilla
Firefox

Internet
Explorer

Opera

Safari

1.7

October 2006

1.6 + Pythonic generators + Iterators + let

 

2.0

 

 

 

-> Firefox 2.0에서 javascript 1.7을 지원한다고 합니다.

 

 3. JavaScript 1.7 기능들에 대해서 JS1.7 버전에서 정상 동작하는 것을 확인하였습니다.

<https://developer.mozilla.org/en/New_in_JavaScript_1.7>

 

따라서, 명시적이지는 않지만 지원한다고 말할 수 있겠습니다.

 

 

▣ Shell에서부터의 개략적인 흐름

Javascript 문장이 입력으로 주어졌을 때 Spider monkey 내에서는 Compile 단계를 거쳐 byte code를 만듭니다.

해당 bytecode는 Interpret 단계를 거쳐 실행을 하게 됩니다.

 

 flow.JPG

 

Example of byte code

– “1”을 입력한 경우 길이 3인 byte codecompile됩니다. 3F 02 C3

3F(opcode)        “one”

02(opcode)        “push”

C3(opcode)        “stop”

 

opcode에 대한 정의는 jsopcode.tbl 파일을 나열되어 있습니다.

/* legend: op         val name          image       len use def prec  format */

/* Longstanding JavaScript bytecodes. */

OPDEF(JSOP_NOP,       0,  "nop",        NULL,         1,  0,  0,  0,  JOF_BYTE)

OPDEF(JSOP_PUSH,      1,  "push",       NULL,         1,  0,  1,  0,  JOF_BYTE)

……

 

▣ TIP

 

▣ Interpreter part

 

금일 Interpreter 관련 코드를 살펴 보았습니다.

Interpret 기능은 jsinterp.c 파일 내 js_Interpret 함수가 핵심 역할을 수행하고 있습니다.

함수의 양은 엄청 크며 while 문 안에서 switch 문이 opcode(명령어)를 하나씩 실행하는 구조로 되어 있습니다.

while{

           switch() {

           case:

                     break;

           }

}

 

js_Interpret 함수의 parameter

1. JSContext* cx             [IN] bytecode가 실행되어야 할 context를 가리킵니다.

2. jsbytecode* pc (uint8)   [IN] bytecode

3. jsval* result               [OUT] 결과 값

 

js_Interpret 함수 내 몇몇 주요 변수

JSRuntime* rt                context가 가진 런타임

JSStackFrame* fp            context가 가진 스택 프레임

JSScript* script               스택 프레임이 가진 script

jsval* sp                      스택 포인터, fp->spbase와 동일시 됩니다.

……

 

Function 처리에 대한 고찰

Function은 (예상) compile 단계에서 다른 곳에 기억해 두고 있습니다.

byte code에서 function call을 하게 되면 JSInlineFrame를 사용하여 해당 위치로 옮겨 가서 동작을 수행하게 됩니다.

 

▣ Developer로서 spice monkey의 활용 매커니즘.

 ex. 브라우저와의 연동

 

 ▣ Compiler

script 구문을 입력으로 해서 token을 얻어 AST를 만들고 이를 byte code로 변환하는 과정을 말합니다.

 

 

NewOrRecycledNode 함수는 JSParseNode를 생성해 준다.

- JSTreeContext::nodelist : 생성할 node(JSParseNode)를 리스트로 가진다.

- nodelist가 비어 있으면 JSContext::tempPool(JSArenaPool)로부터 얻는다.

 

 Statements 함수는 하나의 구간({..})을 가리킨다.

js_PushStatement

js_PopStatement

 

 JSParseNode::pn_type : 토큰 값

 JSParseNode::pn_op : op code 값

 JSParseNode::pn_arity : set의 성격을 나타낸다.

 JSParseNode::pn_u : 실제 내용

 

 

 * Label        Variant     Members
 * -----        -------     -------
 * <Definitions>
 * TOK_FUNCTION func        pn_funAtom: atom holding function object containing
 *                            arg and var properties.  We create the function
 *                            object at parse (not emit) time to specialize arg
 *                            and var bytecodes early.인자와 변수를 가진 함수를 가지는 기본 요소.
 *                            인자와 변수를 가진 함수를 가지는 기본 요소.
 *                          pn_body: TOK_LC node for function body statements   - 
 *                          pn_flags: TCF_FUN_* flags (see jsemit.h) collected   - 
 *                            while parsing the function's body
 *                          pn_tryCount: of try statements in function                  - 해당 함수 내 try 구문 개수
 *                        
 * <Statements>
 * TOK_LC       list        pn_head: list of pn_count statements                                             - pn_count개 statement들의 리스트
 * TOK_EXPORT   list        pn_head: list of pn_count TOK_NAMEs or one TOK_STAR            - pn_count 개 TOK_NAME들 또는 *의 리스트
 *                            (which is not a multiply node)
 * TOK_IMPORT   list        pn_head: list of pn_count sub-trees of the form                            - pn_count개 subtree의 리스트
 *                            a.b.*, a[b].*, a.*, a.b, or a[b] -- but never a.
 *                            Each member is expressed with TOK_DOT or TOK_LB.
 *                            Each sub-tree's root node has a pn_op in the set
 *                            JSOP_IMPORT{ALL,PROP,ELEM}
 * TOK_IF       ternary     pn_kid1: cond, pn_kid2: then, pn_kid3: else or null                           - 조건, true일 경우, false일 경우로 나뉜다.
 * TOK_SWITCH   binary      pn_left: discriminant                                                                - 판별식
 *                          pn_right: list of TOK_CASE nodes, with at most one                                - CASE node 리스트
 *                            TOK_DEFAULT node, or if there are let bindings
 *                            in the top level of the switch body's cases, a
 *                            TOK_LEXICALSCOPE node that contains the list of
 *                            TOK_CASE nodes.
 * TOK_CASE,    binary      pn_left: case expr or null if TOK_DEFAULT
 * TOK_DEFAULT              pn_right: TOK_LC node for this case's statements
 *                          pn_val: constant value if lookup or table switch
 * TOK_WHILE    binary      pn_left: cond, pn_right: body                                                      - 조건, body
 * TOK_DO       binary      pn_left: body, pn_right: cond                                                        - body, 조건
 * TOK_FOR      binary      pn_left: either                                                                             - binary??
 *                            for/in loop: a binary TOK_IN node with
 *                              pn_left:  TOK_VAR or TOK_NAME to left of 'in'
 *                                if TOK_VAR, its pn_extra may have PNX_POPVAR
 *                                and PNX_FORINVAR bits set
 *                              pn_right: object expr to right of 'in'
 *                            for(;;) loop: a ternary TOK_RESERVED node with
 *                              pn_kid1:  init expr before first ';'
 *                              pn_kid2:  cond expr before second ';'
 *                              pn_kid3:  update expr after second ';'
 *                              any kid may be null
 *                          pn_right: body
 * TOK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
 * TOK_TRY      ternary     pn_kid1: try block
 *                          pn_kid2: null or TOK_RESERVED list of
 *                          TOK_LEXICALSCOPE nodes, each with pn_expr pointing
 *                          to a TOK_CATCH node
 *                          pn_kid3: null or finally block
 * TOK_CATCH    ternary     pn_kid1: TOK_NAME, TOK_RB, or TOK_RC catch var node
 *                                   (TOK_RB or TOK_RC if destructuring)
 *                          pn_kid2: null or the catch guard expression
 *                          pn_kid3: catch block statements
 * TOK_BREAK    name        pn_atom: label or null
 * TOK_CONTINUE name        pn_atom: label or null
 * TOK_WITH     binary      pn_left: head expr, pn_right: body
 * TOK_VAR      list        pn_head: list of pn_count TOK_NAME nodes
 *                                   each name node has
 *                                     pn_atom: variable name
 *                                     pn_expr: initializer or null
 * TOK_RETURN   unary       pn_kid: return expr or null
 * TOK_SEMI     unary       pn_kid: expr or null statement
 * TOK_COLON    name        pn_atom: label, pn_expr: labeled statement
 *
 * <Expressions>
 * All left-associated binary trees of the same type are optimized into lists
 * to avoid recursion when processing expression chains.
 * TOK_COMMA    list        pn_head: list of pn_count comma-separated exprs
 * TOK_ASSIGN   binary      pn_left: lvalue, pn_right: rvalue
 *                          pn_op: JSOP_ADD for +=, etc.
 * TOK_HOOK     ternary     pn_kid1: cond, pn_kid2: then, pn_kid3: else
 * TOK_OR       binary      pn_left: first in || chain, pn_right: rest of chain
 * TOK_AND      binary      pn_left: first in && chain, pn_right: rest of chain
 * TOK_BITOR    binary      pn_left: left-assoc | expr, pn_right: ^ expr
 * TOK_BITXOR   binary      pn_left: left-assoc ^ expr, pn_right: & expr
 * TOK_BITAND   binary      pn_left: left-assoc & expr, pn_right: EQ expr
 * TOK_EQOP     binary      pn_left: left-assoc EQ expr, pn_right: REL expr
 *                          pn_op: JSOP_EQ, JSOP_NE, JSOP_NEW_EQ, JSOP_NEW_NE
 * TOK_RELOP    binary      pn_left: left-assoc REL expr, pn_right: SH expr
 *                          pn_op: JSOP_LT, JSOP_LE, JSOP_GT, JSOP_GE
 * TOK_SHOP     binary      pn_left: left-assoc SH expr, pn_right: ADD expr
 *                          pn_op: JSOP_LSH, JSOP_RSH, JSOP_URSH
 * TOK_PLUS,    binary      pn_left: left-assoc ADD expr, pn_right: MUL expr
 *                          pn_extra: if a left-associated binary TOK_PLUS
 *                            tree has been flattened into a list (see above
 *                            under <Expressions>), pn_extra will contain
 *                            PNX_STRCAT if at least one list element is a
 *                            string literal (TOK_STRING); if such a list has
 *                            any non-string, non-number term, pn_extra will
 *                            contain PNX_CANTFOLD.
 *                          pn_
 * TOK_MINUS                pn_op: JSOP_ADD, JSOP_SUB
 * TOK_STAR,    binary      pn_left: left-assoc MUL expr, pn_right: UNARY expr
 * TOK_DIVOP                pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
 * TOK_UNARYOP  unary       pn_kid: UNARY expr, pn_op: JSOP_NEG, JSOP_POS,
 *                          JSOP_NOT, JSOP_BITNOT, JSOP_TYPEOF, JSOP_VOID
 * TOK_INC,     unary       pn_kid: MEMBER expr
 * TOK_DEC
 * TOK_NEW      list        pn_head: list of ctor, arg1, arg2, ... argN
 *                          pn_count: 1 + N (where N is number of args)
 *                          ctor is a MEMBER expr
 * TOK_DELETE   unary       pn_kid: MEMBER expr
 * TOK_DOT,     name        pn_expr: MEMBER expr to left of .
 * TOK_DBLDOT               pn_atom: name to right of .
 * TOK_LB       binary      pn_left: MEMBER expr to left of [
 *                          pn_right: expr between [ and ]
 * TOK_LP       list        pn_head: list of call, arg1, arg2, ... argN
 *                          pn_count: 1 + N (where N is number of args)
 *                          call is a MEMBER expr naming a callable object
 * TOK_RB       list        pn_head: list of pn_count array element exprs
 *                          [,,] holes are represented by TOK_COMMA nodes
 *                          #n=[...] produces TOK_DEFSHARP at head of list
 *                          pn_extra: PN_ENDCOMMA if extra comma at end
 * TOK_RC       list        pn_head: list of pn_count TOK_COLON nodes where
 *                          each has pn_left: property id, pn_right: value
 *                          #n={...} produces TOK_DEFSHARP at head of list
 * TOK_DEFSHARP unary       pn_num: jsint value of n in #n=
 *                          pn_kid: null for #n=[...] and #n={...}, primary
 *                          if #n=primary for function, paren, name, object
 *                          literal expressions
 * TOK_USESHARP nullary     pn_num: jsint value of n in #n#
 * TOK_RP       unary       pn_kid: parenthesized expression
 * TOK_NAME,    name        pn_atom: name, string, or object atom
 * TOK_STRING,              pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
 *                                 JSOP_REGEXP
 * TOK_OBJECT               If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
 *                          with pn_slot >= 0 and pn_attrs telling const-ness
 * TOK_NUMBER   dval        pn_dval: double value of numeric literal
 * TOK_PRIMARY  nullary     pn_op: JSOp bytecode
 *
 * <E4X node descriptions>
 * TOK_ANYNAME  nullary     pn_op: JSOP_ANYNAME
 *                          pn_atom: cx->runtime->atomState.starAtom
 * TOK_AT       unary       pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
 * TOK_DBLCOLON binary      pn_op: JSOP_QNAME
 *                          pn_left: TOK_ANYNAME or TOK_NAME node
 *                          pn_right: TOK_STRING "*" node, or expr within []
 *              name        pn_op: JSOP_QNAMECONST
 *                          pn_expr: TOK_ANYNAME or TOK_NAME left operand
 *                          pn_atom: name on right of ::
 * TOK_XMLELEM  list        XML element node
 *                          pn_head: start tag, content1, ... contentN, end tag
 *                          pn_count: 2 + N where N is number of content nodes
 *                                    N may be > x.length() if {expr} embedded
 * TOK_XMLLIST  list        XML list node
 *                          pn_head: content1, ... contentN
 * TOK_XMLSTAGO, list       XML start, end, and point tag contents
 * TOK_XMLETAGC,            pn_head: tag name or {expr}, ... XML attrs ...
 * TOK_XMLPTAGO
 * TOK_XMLNAME  nullary     pn_atom: XML name, with no {expr} embedded
 * TOK_XMLNAME  list        pn_head: tag name or {expr}, ... name or {expr}
 * TOK_XMLATTR, nullary     pn_atom: attribute value string; pn_op: JSOP_STRING
 * TOK_XMLCDATA,
 * TOK_XMLCOMMENT
 * TOK_XMLPI    nullary     pn_atom: XML processing instruction target
 *                          pn_atom2: XML PI content, or null if no content
 * TOK_XMLTEXT  nullary     pn_atom: marked-up text, or null if empty string
 * TOK_LC       unary       {expr} in XML tag or content; pn_kid is expr
 *
 * So an XML tag with no {expr} and three attributes is a list with the form:
 *
 *    (tagname attrname1 attrvalue1 attrname2 attrvalue2 attrname2 attrvalue3)
 *
 * An XML tag with embedded expressions like so:
 *
 *    <name1{expr1} name2{expr2}name3={expr3}>
 *
 * would have the form:
 *
 *    ((name1 {expr1}) (name2 {expr2} name3) {expr3})
 *
 * where () bracket a list with elements separated by spaces, and {expr} is a
 * TOK_LC unary node with expr as its kid.
 *
 * Thus, the attribute name/value pairs occupy successive odd and even list
 * locations, where pn_head is the TOK_XMLNAME node at list location 0.  The
 * parser builds the same sort of structures for elements:
 *
 *    <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a>
 *
 * translates to:
 *
 *    ((a x {x}) 'Hi there!' ((b y {y}) 'How are you?') ((answer) {x + y}))
 *
 * <Non-E4X node descriptions, continued>
 *
 * Label              Variant   Members
 * -----              -------   -------
 * TOK_LEXICALSCOPE   name      pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR
 *                              pn_atom: block object
 *                              pn_expr: block body
 * TOK_ARRAYCOMP      list      pn_head: list of pn_count (1 or 2) elements
 *                              if pn_count is 2, first element is #n=[...]
 *                                last element is block enclosing for loop(s)
 *                                and optionally if-guarded TOK_ARRAYPUSH
 *                              pn_extra: stack slot, used during code gen
 * TOK_ARRAYPUSH      unary     pn_op: JSOP_ARRAYCOMP
 *                              pn_kid: array comprehension expression