Bug 623379: runtests: Check for java binary before asc invokes (r=fklockii)
[tamarin-stm.git] / eval / eval-abc.cpp
blob6c9d906bba5403b61f7ac68dc6786916465aa23b
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
14 * License.
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.
23 * Contributor(s):
24 * Adobe AS3 Team
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 #include "avmplus.h"
42 #ifdef VMCFG_EVAL
44 #include "eval.h"
46 namespace avmplus
48 namespace RTC
50 using namespace ActionBlockConstants;
52 template<class T> static uint32_t computeSize(Seq<T>* xs)
54 uint32_t size = 0;
55 for ( ; xs != NULL ; xs = xs->tl )
56 size += xs->hd->size();
57 return 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);
64 return b;
67 template<class T> static uint32_t length(Seq<T>* xs)
69 uint32_t n = 0;
70 for ( ; xs != NULL ; xs = xs->tl )
71 n++;
72 return n;
75 static uint8_t* emitBytes(uint8_t* buf, ByteBuffer * const src)
77 uint32_t nbytes = src->size();
78 src->serialize(buf);
79 return buf + nbytes;
82 // Never called, but gcc gets very annoyed if a class with virtual methods does not
83 // have a virtual destructor.
84 ABCChunk::~ABCChunk()
88 ABCFile::ABCFile(Compiler* compiler)
89 : major_version(46)
90 , minor_version(16)
91 , NO_VALUE(~0U)
92 , 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
101 , methodCount(0)
102 , metadataCount(0)
103 , instanceCount(0)
104 , classCount(0)
105 , scriptCount(0)
106 , methodbodyCount(0)
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)
117 , methods(allocator)
118 , metadatas(allocator)
119 , instances(allocator)
120 , classes(allocator)
121 , scripts(allocator)
122 , bodies(allocator)
126 uint32_t ABCFile::addInt(int32_t i)
128 intBuf.emitS32(i);
129 return intCount++;
132 uint32_t ABCFile::addUInt(uint32_t u)
134 uintBuf.emitU32(u);
135 return uintCount++;
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);
152 return s->ident;
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)
162 uint32_t i;
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)
166 return i;
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)
175 uint32_t length = 0;
176 uint32_t i, j;
177 Seq<uint32_t>* tmp;
179 for ( tmp=nss ; tmp != NULL ; tmp=tmp->tl)
180 length++;
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)
187 goto loop_end;
188 return i;
191 loop_end:
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);
200 return nssetCount++;
203 uint32_t ABCFile::multinameLookup(uint8_t kind, uint32_t ns_or_nsset, uint32_t name)
205 Seq<ABCMultinameInfo*>* mns;
206 uint32_t i;
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)
210 return i;
212 multinameBuf.emitU8(kind);
213 switch (kind) {
214 case CONSTANT_QnameA:
215 case CONSTANT_Qname:
216 multinameBuf.emitU30(ns_or_nsset);
217 multinameBuf.emitU30(name);
218 break;
220 case CONSTANT_RTQnameA:
221 case CONSTANT_RTQname:
222 multinameBuf.emitU30(name);
223 break;
225 case CONSTANT_RTQnameLA:
226 case CONSTANT_RTQnameL:
227 break;
229 case CONSTANT_MultinameA:
230 case CONSTANT_Multiname:
231 multinameBuf.emitU30(name);
232 multinameBuf.emitU30(ns_or_nsset);
233 break;
235 case CONSTANT_MultinameLA:
236 case CONSTANT_MultinameL:
237 multinameBuf.emitU30(ns_or_nsset);
238 break;
240 default:
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-- )
254 return mns->hd;
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:
264 return true;
265 default:
266 return false;
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:
277 return true;
278 default:
279 return false;
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());
297 reported_size = (4 +
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 );
346 return b;
349 ABCTraitsTable::ABCTraitsTable(Compiler* compiler)
350 : traitsCount(0)
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 );
367 return b;
370 uint32_t ABCTrait::size()
372 // no provision for metadata
373 reported_size = (lenU30(name) +
374 1 /* kind */ +
375 dataSize());
376 return reported_size;
379 uint8_t *ABCTrait::serialize(uint8_t* b)
381 DEBUG_ONLY( uint8_t* b0 = b; )
382 b = emitU30(b, name);
383 AvmAssert(kind < 8);
384 *b++ = (uint8_t)kind;
385 b = serializeData(b);
386 AvmAssert( b == b0 + reported_size );
387 return b;
390 uint32_t ABCSlotTrait::dataSize()
392 uint32_t slot_id = 0, vindex = 0;
393 return (lenU30(slot_id) +
394 lenU30(type_name) +
395 lenU30(vindex) +
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);
405 if (vindex != 0)
406 *b++ = (uint8_t)vkind;
407 return b;
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);
421 return b;
424 ABCScriptInfo::ABCScriptInfo(Compiler* compiler, ABCMethodInfo* init_method, ABCTraitsTable* traits)
425 : index(compiler->abc.addScript(this))
426 , init_method(init_method)
427 , traits(traits)
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 );
443 return b;
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)
451 , traits(traits)
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() +
464 exceptions.size() +
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 );
482 return b;
485 ABCMethodInfo::ABCMethodInfo(Compiler* compiler,
486 uint32_t name,
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))
493 , name(name)
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)
499 , flags(~0U)
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);
512 option_size += 1;
514 reported_size = (lenU30(param_count) +
515 lenU30(return_type) +
516 param_size +
517 lenU30(name) +
518 1 /* flags */ +
519 option_size +
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;
530 else
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 );
546 return b;
549 ABCExceptionTable::ABCExceptionTable(Compiler* compiler)
550 : exceptionCount(0)
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 );
570 return b;
573 ABCExceptionInfo::ABCExceptionInfo(uint32_t from, uint32_t to, uint32_t target, uint32_t exception_type, uint32_t var_name)
574 : from(from)
575 , to(to)
576 , target(target)
577 , exception_type(exception_type)
578 , var_name(var_name)
582 uint32_t ABCExceptionInfo::size()
584 reported_size = (lenU30(from) +
585 lenU30(to) +
586 lenU30(target) +
587 lenU30(exception_type) +
588 lenU30(var_name));
589 return reported_size;
592 uint8_t* ABCExceptionInfo::serialize(uint8_t* b)
594 DEBUG_ONLY( uint8_t* b0 = b; )
595 b = emitU30(b, from);
596 b = emitU30(b, to);
597 b = emitU30(b, target);
598 b = emitU30(b, exception_type);
599 b = emitU30(b, var_name);
600 AvmAssert( b == b0 + reported_size );
601 return b;
604 #if 0
606 class ABCInstanceInfo
608 function ABCInstanceInfo(name, super_name, flags, protectedNS, interfaces) {
609 this.name = name;
610 this.super_name = super_name;
611 this.flags = flags;
612 this.protectedNS = protectedNS;
613 this.interfaces = interfaces;
614 this.traits = [];
617 function setIInit(x) {
618 iinit = x;
621 function addTrait(t) {
622 return traits.push(t)-1;
625 function serialize(bs) {
626 let i, limit;
628 Util::assert( iinit != undefined || (flags & CONSTANT_ClassInterface) != 0);
630 bs.uint30(name);
631 bs.uint30(super_name);
632 bs.uint8(flags);
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]);
640 bs.uint30(iinit);
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;
650 class ABCClassInfo
652 function setCInit(cinit) {
653 this.cinit = cinit;
656 function addTrait(t) {
657 return traits.push(t)-1;
660 function serialize(bs) {
661 Util::assert( cinit != undefined );
662 bs.uint30(cinit);
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 = [];
672 #endif // 0
676 #endif // VMCFG_EVAL