1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2008
21 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 // This file is included into eval.h
46 Label() : address(~0U), backpatches(NULL
) {}
47 uint32_t address
; // either ~0U or the address of the label
48 Seq
<uint32_t>* backpatches
; // not a SeqBuilder so that we don't have to spend space on storing an allocator in every label object
53 DefaultValue(uint32_t tag
, uint32_t index
) : tag(tag
), index(index
) {}
75 Ctx(CtxType tag
, Ctx
* next
)
84 bool mustPushThis(); // context requires a 'this' value to be pushed onto the scope chain
85 bool mustPushScopeReg(); // context requires a scope object stored in a scope register to be pushed onto the scope chain
87 VarScopeCtx
* findVarScope(); // Should never be NULL
90 class ControlFlowCtx
: public Ctx
{
92 ControlFlowCtx(CtxType tag
, Label
* label
, Ctx
* ctx0
)
100 class BreakCtx
: public ControlFlowCtx
{
102 BreakCtx(Label
* label
, Ctx
* ctx0
, Str
* label_name
=NULL
)
103 : ControlFlowCtx(CTX_Break
, label
, ctx0
)
104 , label_name(label_name
)
107 Str
* const label_name
;
110 class ContinueCtx
: public ControlFlowCtx
{
112 ContinueCtx(Label
* label
, Seq
<Str
*>* label_names
, Ctx
* ctx0
)
113 : ControlFlowCtx(CTX_Continue
, label
, ctx0
)
114 , label_names(label_names
)
117 Seq
<Str
*>* const label_names
;
120 // Represents a scope to restore to the scope chain, pushed by 'with'
121 // or 'catch' or reified activation objects, see subclasses.
123 class ScopeCtx
: public Ctx
{
125 ScopeCtx(CtxType tag
, uint32_t scope_reg
, Ctx
* ctx0
)
127 , scope_reg(scope_reg
)
130 const uint32_t scope_reg
;
133 class WithCtx
: public ScopeCtx
{
135 WithCtx(uint32_t scope_reg
, Ctx
* ctx0
)
136 : ScopeCtx(CTX_With
, scope_reg
, ctx0
)
141 struct CatchCtx
: public ScopeCtx
{
142 CatchCtx(uint32_t scope_reg
, Ctx
* ctx0
)
143 : ScopeCtx(CTX_Catch
, scope_reg
, ctx0
)
148 class ActivationCtx
: public ScopeCtx
{
150 ActivationCtx(uint32_t scope_reg
, Ctx
* ctx0
)
151 : ScopeCtx(CTX_Activation
, scope_reg
, ctx0
)
156 class FinallyCtx
: public Ctx
{
158 FinallyCtx(Allocator
* allocator
, Label
* Lfinally
, uint32_t returnreg
, Ctx
* ctx0
)
159 : Ctx(CTX_Finally
, ctx0
)
161 , returnreg(returnreg
)
163 , returnLabels(allocator
)
167 uint32_t addReturnLabel(Label
* l
);
169 Label
* const Lfinally
;
170 const uint32_t returnreg
;
172 SeqBuilder
<Label
*> returnLabels
;
175 class VarScopeCtx
: public Ctx
{
177 VarScopeCtx(CtxType tag
, uint32_t nsset
, Seq
<Namespace
*>* openNamespaces
, Allocator
* allocator
, Ctx
* prev
)
180 , openNamespaces(openNamespaces
)
184 const uint32_t nsset
; // Will be something other than 0 if this variable scope has a multiname qualifier (namespace set)
185 Seq
<Namespace
*>* const openNamespaces
; // Not including ""
188 class FunctionCtx
: public VarScopeCtx
{
190 FunctionCtx(Allocator
* allocator
, uint32_t nsset
, Seq
<Namespace
*>* openNamespaces
, Ctx
* prev
)
191 : VarScopeCtx(CTX_Function
, nsset
, openNamespaces
, allocator
, prev
)
196 class ProgramCtx
: public VarScopeCtx
{
198 ProgramCtx(Allocator
* allocator
, uint32_t nsset
, Seq
<Namespace
*>* openNamespaces
, uint32_t capture_reg
)
199 : VarScopeCtx(CTX_Program
, nsset
, openNamespaces
, allocator
, NULL
)
200 , capture_reg(capture_reg
)
203 const uint32_t capture_reg
;
207 * Instruction and value emitter.
209 * A 'cogen' abstracts away the details of emitting bytecodes and constant
214 Cogen(Compiler
* compiler
, ABCFile
* abc
, ABCTraitsTable
* traits
, ABCMethodBodyInfo
* body
, uint32_t first_temp
=1);
216 /* Instruction emitters. Most of these are trivially expanded
217 * inline to other calls; some have more complex logic. For
218 * example, I_getlocal(0) expands to OP_getlocal0, the
219 * dxns instructions set the uses_dxns flag, and the debug
220 * instructions check whether debugging is enabled. All methods
221 * help compute the heights of the value and scope stacks.
223 * Please maintain an alphabetical list.
227 void I_astype(uint32_t index
);
233 void I_call(uint32_t argc
);
234 void I_callmethod(uint32_t index
, uint32_t nargs
);
235 void I_callproperty(uint32_t index
, uint32_t nargs
);
236 void I_callproplex(uint32_t index
, uint32_t nargs
);
237 void I_callpropvoid(uint32_t index
, uint32_t nargs
);
238 void I_callstatic(uint32_t index
, uint32_t nargs
);
239 void I_callsuper(uint32_t index
, uint32_t nargs
);
240 void I_callsupervoid(uint32_t index
, uint32_t nargs
);
241 void I_construct(uint32_t argc
);
242 void I_constructprop(uint32_t index
, uint32_t nargs
);
243 void I_constructsuper(uint32_t argc
);
244 void I_checkfilter();
245 void I_coerce(uint32_t index
);
254 void I_debug(uint8_t debug_type
, uint32_t index
, uint8_t reg
, uint32_t extra
=0);
255 void I_debugfile(uint32_t index
);
256 void I_debugline(uint32_t linenum
);
257 void I_declocal(uint32_t reg
);
258 void I_declocal_i(uint32_t reg
);
260 void I_decrement_i();
261 void I_deleteproperty(uint32_t index
);
263 void I_dxns(uint32_t index
);
269 void I_findproperty(uint32_t index
);
270 void I_findpropstrict(uint32_t index
);
271 void I_getdescendants(uint32_t index
);
272 void I_getglobalscope();
273 void I_getglobalslot(uint32_t index
);
274 void I_getlex(uint32_t index
);
275 void I_getlocal(uint32_t index
);
276 void I_getouterscope(uint32_t index
);
277 void I_getproperty(uint32_t index
);
278 void I_getscopeobject(uint32_t index
);
279 void I_getslot(uint32_t index
);
280 void I_getsuper(uint32_t index
);
281 void I_greaterequals();
282 void I_greaterthan();
284 void I_hasnext2(uint32_t object_reg
, uint32_t index_reg
);
285 void I_ifeq(Label
* label
);
286 void I_iffalse(Label
* label
);
287 void I_ifge(Label
* label
);
288 void I_ifgt(Label
* label
);
289 void I_ifle(Label
* label
);
290 void I_iflt(Label
* label
);
291 void I_ifne(Label
* label
);
292 void I_ifnge(Label
* label
);
293 void I_ifngt(Label
* label
);
294 void I_ifnle(Label
* label
);
295 void I_ifnlt(Label
* label
);
296 void I_ifstricteq(Label
* label
);
297 void I_ifstrictne(Label
* label
);
298 void I_iftrue(Label
* label
);
300 void I_inclocal(uint32_t reg
);
301 void I_inclocal_i(uint32_t reg
);
303 void I_increment_i();
304 void I_initproperty(uint32_t index
);
306 void I_istype(uint32_t index
);
308 void I_jump(Label
* label
);
309 void I_kill(uint32_t index
);
310 void I_label(Label
* label
);
313 void I_lookupswitch(Label
* default_label
, Label
** case_labels
, uint32_t ncases
);
320 void I_newactivation();
321 void I_newarray(uint32_t nvalues
);
322 void I_newcatch(uint32_t index
);
323 void I_newclass(uint32_t index
);
324 void I_newfunction(uint32_t index
);
325 void I_newobject(uint32_t npairs
);
326 void I_newvoid(uint32_t index
);
333 void I_pushbyte(int8_t b
);
335 void I_pushdouble(uint32_t index
);
336 void I_pushint(uint32_t index
);
337 void I_pushnamespace(uint32_t index
);
341 void I_pushshort(int16_t v
);
342 void I_pushstring(uint32_t index
);
344 void I_pushuint(uint32_t index
);
345 void I_pushundefined();
347 void I_returnvalue();
350 void I_setglobalslot(uint32_t index
);
351 void I_setlocal(uint32_t index
);
352 void I_setproperty(uint32_t index
);
353 void I_setslot(uint32_t index
);
354 void I_setsuper(uint32_t index
);
355 void I_strictequals();
362 void I_opcode(AbcOpcode opcode
);
364 uint32_t emitString(Str
* value
); // cpool index
365 uint32_t emitInt(int32_t value
); // cpool index
366 uint32_t emitUInt(uint32_t value
); // cpool index
367 uint32_t emitDouble(double value
); // cpool index
368 uint32_t emitNamespace(uint32_t name
);
369 uint32_t emitSlotTrait(uint32_t name
, uint32_t type
);
370 uint32_t emitConstTrait(uint32_t name
, uint32_t type
);
371 uint32_t emitMethodTrait(uint32_t name
, uint32_t method
);
372 uint32_t emitException(uint32_t from
, uint32_t to
, uint32_t target
, uint32_t type
, uint32_t name_index
);
374 static uint32_t emitTypeName(Compiler
* abc
, QualifiedName
* t
);
378 void unstructuredControlFlow(Ctx
* ctx
, bool (hit
)(Ctx
*,void*), void* package
, bool jump
, SyntaxError msg
, uint32_t pos
=0);
379 void standardMethod(bool is_function
, Seq
<Str
*>* params
, Seq
<FunctionDefn
*>* functions
, Seq
<Str
*>* vars
, Seq
<Stmt
*>* stmts
);
380 uint32_t arguments(Seq
<Expr
*>* args
, Ctx
* ctx
);
383 AbcOpcode
binopToOpcode(Binop op
, bool* isNegated
);
384 uint32_t buildNssetWithPublic(Seq
<Namespace
*>* ns
);
386 Compiler
* const compiler
;
388 Allocator
* const allocator
;
390 uint32_t getMaxStack() const;
391 uint32_t getMaxScope() const;
392 uint32_t getLocalCount() const;
393 uint32_t getCodeLength() const;
394 uint8_t getFlags() const;
395 uint8_t* serializeCodeBytes(uint8_t* b
) const;
398 void callMN(AbcOpcode op
, uint32_t index
, uint32_t nargs
);
399 void propU30(AbcOpcode op
, uint32_t index
);
400 void emitOp(AbcOpcode op
);
401 void emitOpU30(AbcOpcode op
, uint32_t u30
);
402 void emitOpU30Special(AbcOpcode op
, uint32_t u30
, uint32_t stack_adjust
);
403 void emitOpU30U30(AbcOpcode op
, uint32_t u30_1
, uint32_t u30_2
);
404 void emitOpU8(AbcOpcode op
, uint8_t b
);
405 void emitOpS8(AbcOpcode op
, int8_t b
);
406 void emitOpS16(AbcOpcode op
, uint16_t s
);
407 void emitJump(AbcOpcode op
, Label
* label
);
408 void fixupBackpatches(uint8_t* b
) const;
409 void stackMovement(AbcOpcode opcode
);
410 void stackMovement(AbcOpcode opcode
, bool hasRTNS
, bool hasRTName
, uint32_t argc
);
412 // Mapping from subset of tokens to attributes and operator values
413 static const struct BinopMapping
{
414 unsigned isNegated
:1;
415 unsigned abcOpcode
:8;
420 SeqBuilder
<Label
*> labels
;
421 ABCTraitsTable
* const traits
;
422 ABCMethodBodyInfo
* const body
;
423 uint32_t last_linenum
;
424 uint32_t label_counter
;
425 uint32_t temp_counter
;
427 bool need_activation
;
428 uint32_t stack_depth
;
429 uint32_t max_stack_depth
;
430 uint32_t scope_depth
;