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 ***** */
50 using namespace ActionBlockConstants
;
52 template<class T
> static uint32_t computeSize(Seq
<T
>* xs
)
55 for ( ; xs
!= NULL
; xs
= xs
->tl
)
56 size
+= xs
->hd
->size();
60 template<class T
> static uint8_t* serializeSeq(uint8_t* b
, Seq
<T
>* xs
)
62 for ( ; xs
!= NULL
; xs
= xs
->tl
)
63 b
= xs
->hd
->serialize(b
);
67 template<class T
> static uint32_t length(Seq
<T
>* xs
)
70 for ( ; xs
!= NULL
; xs
= xs
->tl
)
75 static uint8_t* emitBytes(uint8_t* buf
, ByteBuffer
* const src
)
77 uint32_t nbytes
= src
->size();
82 // Never called, but gcc gets very annoyed if a class with virtual methods does not
83 // have a virtual destructor.
88 ABCFile::ABCFile(Compiler
* compiler
)
93 , allocator(compiler
->allocator
)
94 , intCount(1) // entry 0 not present
95 , uintCount(1) // entry 0 not present
96 , doubleCount(1) // entry 0 not present
97 , stringCount(1) // entry 0 not present
98 , namespaceCount(1) // entry 0 not present
99 , nssetCount(1) // entry 0 not present
100 , multinameCount(1) // entry 0 not present
107 , intBuf(allocator
, 16)
108 , uintBuf(allocator
, 16)
109 , doubleBuf(allocator
, 32)
110 , stringBuf(allocator
)
111 , namespaceBuf(allocator
, 16)
112 , nssetBuf(allocator
, 16)
113 , multinameBuf(allocator
, 16)
114 , namespaces(allocator
)
115 , namespaceSets(allocator
)
116 , multinames(allocator
)
118 , metadatas(allocator
)
119 , instances(allocator
)
126 uint32_t ABCFile::addInt(int32_t i
)
132 uint32_t ABCFile::addUInt(uint32_t u
)
138 uint32_t ABCFile::addDouble(double d
)
140 doubleBuf
.emitDouble(d
);
141 return doubleCount
++;
144 uint32_t ABCFile::addString(Str
* s
)
146 if (s
->ident
== ~0U) {
147 s
->ident
= stringCount
++;
148 uint32_t len
= utf8length(s
);
149 stringBuf
.emitU30(len
);
150 stringBuf
.emitUtf8(len
, s
);
155 uint32_t ABCFile::addString(const char* s
)
157 return addString(compiler
->intern(s
));
160 uint32_t ABCFile::addNamespace(uint8_t kind
, uint32_t name
)
163 Seq
<ABCNamespaceInfo
*>* nss
;
164 for ( nss
= namespaces
.get(), i
=1 ; nss
!= NULL
; nss
= nss
->tl
, i
++ )
165 if (nss
->hd
->kind
== kind
&& nss
->hd
->name
== name
)
167 namespaceBuf
.emitU8(kind
);
168 namespaceBuf
.emitU30(name
);
169 namespaces
.addAtEnd(ALLOC(ABCNamespaceInfo
, (kind
, name
)));
170 return namespaceCount
++;
173 uint32_t ABCFile::addNsset(Seq
<uint32_t>* nss
)
179 for ( tmp
=nss
; tmp
!= NULL
; tmp
=tmp
->tl
)
182 Seq
<ABCNamespaceSetInfo
*>* nsss
;
183 for ( nsss
= namespaceSets
.get(), i
=1 ; nsss
!= NULL
; nsss
= nsss
->tl
, i
++ ) {
184 if (length
== nsss
->hd
->length
) {
185 for ( tmp
=nss
, j
=0 ; j
< length
; tmp
=tmp
->tl
, j
++ )
186 if (nsss
->hd
->ns
[j
] != tmp
->hd
)
193 ABCNamespaceSetInfo
* info
= new (allocator
->alloc(sizeof(ABCNamespaceSetInfo
) + (length
-1)*sizeof(uint32_t))) ABCNamespaceSetInfo(length
);
194 nssetBuf
.emitU30(length
);
195 for ( tmp
=nss
, j
=0 ; tmp
!= NULL
; tmp
=tmp
->tl
) {
196 info
->ns
[j
] = tmp
->hd
;
197 nssetBuf
.emitU30(tmp
->hd
);
203 uint32_t ABCFile::multinameLookup(uint8_t kind
, uint32_t ns_or_nsset
, uint32_t name
)
205 Seq
<ABCMultinameInfo
*>* mns
;
208 for ( mns
= multinames
.get(), i
=1 ; mns
!= NULL
; mns
= mns
->tl
, i
++ )
209 if (mns
->hd
->kind
== kind
&& mns
->hd
->ns_or_nsset
== ns_or_nsset
&& mns
->hd
->name
== name
)
212 multinameBuf
.emitU8(kind
);
214 case CONSTANT_QnameA
:
216 multinameBuf
.emitU30(ns_or_nsset
);
217 multinameBuf
.emitU30(name
);
220 case CONSTANT_RTQnameA
:
221 case CONSTANT_RTQname
:
222 multinameBuf
.emitU30(name
);
225 case CONSTANT_RTQnameLA
:
226 case CONSTANT_RTQnameL
:
229 case CONSTANT_MultinameA
:
230 case CONSTANT_Multiname
:
231 multinameBuf
.emitU30(name
);
232 multinameBuf
.emitU30(ns_or_nsset
);
235 case CONSTANT_MultinameLA
:
236 case CONSTANT_MultinameL
:
237 multinameBuf
.emitU30(ns_or_nsset
);
241 compiler
->internalError(0, "Invalid multiname kind");
244 multinames
.addAtEnd(ALLOC(ABCMultinameInfo
, (kind
, ns_or_nsset
, name
)));
245 return multinameCount
++;
248 ABCMultinameInfo
* ABCFile::getMultiname(uint32_t index
)
250 Seq
<ABCMultinameInfo
*>* mns
;
252 for ( mns
= multinames
.get() ; index
> 1 ; mns
= mns
->tl
, index
-- )
257 bool ABCFile::hasRTNS(uint32_t index
)
259 switch (getMultiname(index
)->kind
) {
260 case CONSTANT_RTQname
:
261 case CONSTANT_RTQnameA
:
262 case CONSTANT_RTQnameL
:
263 case CONSTANT_RTQnameLA
:
270 bool ABCFile::hasRTName(uint32_t index
)
272 switch (getMultiname(index
)->kind
) {
273 case CONSTANT_RTQnameL
:
274 case CONSTANT_RTQnameLA
:
275 case CONSTANT_MultinameL
:
276 case CONSTANT_MultinameLA
:
283 uint32_t ABCFile::size()
285 AvmAssert(scriptCount
!= 0);
286 AvmAssert(methodCount
!= 0);
287 AvmAssert(methodbodyCount
!= 0);
288 AvmAssert(classCount
== instanceCount
);
290 uint32_t method_size
= computeSize(methods
.get());
291 uint32_t metadata_size
= computeSize(metadatas
.get());
292 uint32_t instance_size
= computeSize(instances
.get());
293 uint32_t class_size
= computeSize(classes
.get());
294 uint32_t script_size
= computeSize(scripts
.get());
295 uint32_t body_size
= computeSize(bodies
.get());
298 lenU30(intCount
) + intBuf
.size() +
299 lenU30(uintCount
) + uintBuf
.size() +
300 lenU30(doubleCount
) + doubleBuf
.size() +
301 lenU30(stringCount
) + stringBuf
.size() +
302 lenU30(namespaceCount
) + namespaceBuf
.size() +
303 lenU30(nssetCount
) + nssetBuf
.size() +
304 lenU30(multinameCount
) + multinameBuf
.size() +
305 lenU30(methodCount
) + method_size
+
306 lenU30(metadataCount
) + metadata_size
+
307 lenU30(instanceCount
) + instance_size
+ class_size
+
308 lenU30(scriptCount
) + script_size
+
309 lenU30(methodbodyCount
) + body_size
);
310 return reported_size
;
313 uint8_t* ABCFile::serialize(uint8_t* b
)
315 DEBUG_ONLY( uint8_t* b0
= b
; )
316 b
= emitU16(b
, minor_version
);
317 b
= emitU16(b
, major_version
);
319 b
= emitU30(b
, intCount
);
320 b
= emitBytes(b
, &intBuf
);
321 b
= emitU30(b
, uintCount
);
322 b
= emitBytes(b
, &uintBuf
);
323 b
= emitU30(b
, doubleCount
);
324 b
= emitBytes(b
, &doubleBuf
);
325 b
= emitU30(b
, stringCount
);
326 b
= emitBytes(b
, &stringBuf
);
327 b
= emitU30(b
, namespaceCount
);
328 b
= emitBytes(b
, &namespaceBuf
);
329 b
= emitU30(b
, nssetCount
);
330 b
= emitBytes(b
, &nssetBuf
);
331 b
= emitU30(b
, multinameCount
);
332 b
= emitBytes(b
, &multinameBuf
);
334 b
= emitU30(b
, methodCount
);
335 b
= serializeSeq(b
, methods
.get());
336 b
= emitU30(b
, metadataCount
);
337 b
= serializeSeq(b
, metadatas
.get());
338 b
= emitU30(b
, instanceCount
);
339 b
= serializeSeq(b
, instances
.get());
340 b
= serializeSeq(b
, classes
.get());
341 b
= emitU30(b
, scriptCount
);
342 b
= serializeSeq(b
, scripts
.get());
343 b
= emitU30(b
, methodbodyCount
);
344 b
= serializeSeq(b
, bodies
.get());
345 AvmAssert( b
== b0
+ reported_size
);
349 ABCTraitsTable::ABCTraitsTable(Compiler
* compiler
)
351 , traits(compiler
->allocator
)
355 uint32_t ABCTraitsTable::size()
357 reported_size
= lenU30(traitsCount
) + computeSize(traits
.get());
358 return reported_size
;
361 uint8_t* ABCTraitsTable::serialize(uint8_t* b
)
363 DEBUG_ONLY( uint8_t* b0
= b
; )
364 b
= emitU30(b
, traitsCount
);
365 b
= serializeSeq(b
, traits
.get());
366 AvmAssert( b
== b0
+ reported_size
);
370 uint32_t ABCTrait::size()
372 // no provision for metadata
373 reported_size
= (lenU30(name
) +
376 return reported_size
;
379 uint8_t *ABCTrait::serialize(uint8_t* b
)
381 DEBUG_ONLY( uint8_t* b0
= b
; )
382 b
= emitU30(b
, name
);
384 *b
++ = (uint8_t)kind
;
385 b
= serializeData(b
);
386 AvmAssert( b
== b0
+ reported_size
);
390 uint32_t ABCSlotTrait::dataSize()
392 uint32_t slot_id
= 0, vindex
= 0;
393 return (lenU30(slot_id
) +
396 (vindex
!= 0 ? 1 : 0));
399 uint8_t* ABCSlotTrait::serializeData(uint8_t *b
)
401 uint32_t slot_id
= 0, vindex
= 0, vkind
= 0;
402 b
= emitU30(b
, slot_id
);
403 b
= emitU30(b
, type_name
);
404 b
= emitU30(b
, vindex
);
406 *b
++ = (uint8_t)vkind
;
410 uint32_t ABCMethodTrait::dataSize()
412 uint32_t disp_id
= 0;
413 return (lenU30(disp_id
) + lenU30(method_info
));
416 uint8_t* ABCMethodTrait::serializeData(uint8_t* b
)
418 uint32_t disp_id
= 0;
419 b
= emitU30(b
, disp_id
);
420 b
= emitU30(b
, method_info
);
424 ABCScriptInfo::ABCScriptInfo(Compiler
* compiler
, ABCMethodInfo
* init_method
, ABCTraitsTable
* traits
)
425 : index(compiler
->abc
.addScript(this))
426 , init_method(init_method
)
431 uint32_t ABCScriptInfo::size()
433 reported_size
= (lenU30(init_method
->index
) + traits
->size());
434 return reported_size
;
437 uint8_t *ABCScriptInfo::serialize(uint8_t* b
)
439 DEBUG_ONLY( uint8_t* b0
= b
; )
440 b
= emitU30(b
, init_method
->index
);
441 b
= traits
->serialize(b
);
442 AvmAssert( b
== b0
+ reported_size
);
446 ABCMethodBodyInfo::ABCMethodBodyInfo(Compiler
* compiler
, ABCMethodInfo
* method_info
, ABCTraitsTable
* traits
, uint32_t first_temp
)
447 : cogen(compiler
, &compiler
->abc
, traits
, this, first_temp
)
448 , exceptions(compiler
)
449 , index(compiler
->abc
.addMethodBody(this))
450 , method_info(method_info
)
455 uint32_t ABCMethodBodyInfo::size()
457 reported_size
= (lenU30(method_info
->index
) +
458 lenU30(cogen
.getMaxStack()) +
459 lenU30(cogen
.getLocalCount()) +
460 lenU30(0) /* init_scope_depth */ +
461 lenU30(cogen
.getMaxScope()) +
462 lenU30(cogen
.getCodeLength()) +
463 cogen
.getCodeLength() +
465 (traits
? traits
->size() : lenU30(0)));
466 return reported_size
;
469 uint8_t* ABCMethodBodyInfo::serialize(uint8_t* b
)
471 DEBUG_ONLY( uint8_t* b0
= b
; )
472 b
= emitU30(b
, method_info
->index
);
473 b
= emitU30(b
, cogen
.getMaxStack());
474 b
= emitU30(b
, cogen
.getLocalCount());
475 b
= emitU30(b
, 0); /* init_scope_depth */
476 b
= emitU30(b
, cogen
.getMaxScope());
477 b
= emitU30(b
, cogen
.getCodeLength());
478 b
= cogen
.serializeCodeBytes(b
);
479 b
= exceptions
.serialize(b
);
480 b
= (traits
? traits
->serialize(b
) : emitU30(b
, 0));
481 AvmAssert( b
== b0
+ reported_size
);
485 ABCMethodInfo::ABCMethodInfo(Compiler
* compiler
,
487 uint32_t param_count
,
488 Seq
<uint32_t>* param_types
,
489 uint32_t option_count
,
490 Seq
<DefaultValue
*>* default_values
,
491 uint32_t return_type
)
492 : index(compiler
->abc
.addMethod(this))
494 , param_count(param_count
)
495 , param_types(param_types
)
496 , option_count(option_count
)
497 , default_values(default_values
)
498 , return_type(return_type
)
503 uint32_t ABCMethodInfo::size()
505 AvmAssert(flags
!= ~0U);
506 uint32_t param_size
= 0;
507 for ( Seq
<uint32_t>* param_types
= this->param_types
; param_types
!= NULL
; param_types
= param_types
->tl
)
508 param_size
+= lenU30(param_types
->hd
);
509 uint32_t option_size
= option_count
> 0 ? lenU30(option_count
) : 0;
510 for ( Seq
<DefaultValue
*>* default_values
= this->default_values
; default_values
!= NULL
; default_values
= default_values
->tl
) {
511 option_size
+= lenU30(default_values
->hd
->index
);
514 reported_size
= (lenU30(param_count
) +
515 lenU30(return_type
) +
520 0 /* param_names */);
521 return reported_size
;
524 uint8_t* ABCMethodInfo::serialize(uint8_t* b
)
526 DEBUG_ONLY( uint8_t* b0
= b
; )
527 AvmAssert(flags
!= ~0U);
528 if (option_count
> 0)
529 flags
|= abcMethod_HAS_OPTIONAL
;
531 flags
&= ~abcMethod_HAS_OPTIONAL
;
532 b
= emitU30(b
, param_count
);
533 b
= emitU30(b
, return_type
);
534 for ( Seq
<uint32_t>* param_types
= this->param_types
; param_types
!= NULL
; param_types
= param_types
->tl
)
535 b
= emitU30(b
, param_types
->hd
);
536 b
= emitU30(b
, name
);
537 *b
++ = (uint8_t)flags
;
538 if (option_count
> 0) {
539 b
= emitU30(b
, option_count
);
540 for ( Seq
<DefaultValue
*>* default_values
= this->default_values
; default_values
!= NULL
; default_values
= default_values
->tl
) {
541 b
= emitU30(b
, default_values
->hd
->index
);
542 *b
++ = (uint8_t)default_values
->hd
->tag
;
545 AvmAssert( b
== b0
+ reported_size
);
549 ABCExceptionTable::ABCExceptionTable(Compiler
* compiler
)
551 , exceptions(compiler
->allocator
)
555 uint32_t ABCExceptionTable::size()
557 reported_size
= lenU30(exceptionCount
);
558 for ( Seq
<ABCExceptionInfo
*>* exceptions
= this->exceptions
.get() ; exceptions
!= NULL
; exceptions
= exceptions
->tl
)
559 reported_size
+= exceptions
->hd
->size();
560 return reported_size
;
563 uint8_t* ABCExceptionTable::serialize(uint8_t* b
)
565 DEBUG_ONLY( uint8_t* b0
= b
; )
566 b
= emitU30(b
, exceptionCount
);
567 for ( Seq
<ABCExceptionInfo
*>* exceptions
= this->exceptions
.get() ; exceptions
!= NULL
; exceptions
= exceptions
->tl
)
568 b
= exceptions
->hd
->serialize(b
);
569 AvmAssert( b
== b0
+ reported_size
);
573 ABCExceptionInfo::ABCExceptionInfo(uint32_t from
, uint32_t to
, uint32_t target
, uint32_t exception_type
, uint32_t var_name
)
577 , exception_type(exception_type
)
582 uint32_t ABCExceptionInfo::size()
584 reported_size
= (lenU30(from
) +
587 lenU30(exception_type
) +
589 return reported_size
;
592 uint8_t* ABCExceptionInfo::serialize(uint8_t* b
)
594 DEBUG_ONLY( uint8_t* b0
= b
; )
595 b
= emitU30(b
, from
);
597 b
= emitU30(b
, target
);
598 b
= emitU30(b
, exception_type
);
599 b
= emitU30(b
, var_name
);
600 AvmAssert( b
== b0
+ reported_size
);
606 class ABCInstanceInfo
608 function
ABCInstanceInfo(name
, super_name
, flags
, protectedNS
, interfaces
) {
610 this.super_name
= super_name
;
612 this.protectedNS
= protectedNS
;
613 this.interfaces
= interfaces
;
617 function
setIInit(x
) {
621 function
addTrait(t
) {
622 return traits
.push(t
)-1;
625 function
serialize(bs
) {
628 Util::assert( iinit
!= undefined
|| (flags
& CONSTANT_ClassInterface
) != 0);
631 bs
.uint30(super_name
);
633 if (flags
& CONSTANT_ClassProtectedNs
)
634 bs
.uint30(protectedNS
);
635 bs
.uint30(interfaces
.length
);
636 for ( i
=0, limit
=interfaces
.length
; i
< limit
; i
++ ) {
637 Util::assert( interfaces
[i
] != 0 );
638 bs
.uint30(interfaces
[i
]);
641 bs
.uint30(traits
.length
);
642 for ( i
=0, limit
=traits
.length
; i
< limit
; i
++ )
643 traits
[i
].serialize(bs
);
646 // abc-parse.es grubs around here.
647 / *private* / var name
, super_name
, flags
, protectedNS
, interfaces
, iinit
, traits
;
652 function
setCInit(cinit
) {
656 function
addTrait(t
) {
657 return traits
.push(t
)-1;
660 function
serialize(bs
) {
661 Util::assert( cinit
!= undefined
);
663 bs
.uint30(traits
.length
);
664 for ( let i
=0, limit
=traits
.length
; i
< limit
; i
++ )
665 traits
[i
].serialize(bs
);
668 // abc-parse.es grubs around here.
669 /*private*/ var cinit
, traits
= [];