Commit Graph

57 Commits

Author SHA1 Message Date
David Wendt 566b262d60 Move all our custom object implementations into a separate module, and use a macro to implement them. 2020-08-10 16:38:04 -07:00
David Wendt 2f55c08e37 `pushbyte` should generate signed integers rather than `Number`s. 2020-08-10 16:38:04 -07:00
David Wendt d14fa845c2 Remove `Value::Namespace`.
Namespaces as values adds a bunch of extra special cases to the coercion and equality rules that don't really belong there. Namespace itself just returns it's URI as a string, so we can just make `NamespaceObject` do that and then treat it the same way we treat boxed primitives.
2020-08-10 16:38:04 -07:00
David Wendt 65b4392642 Remove `as_number`.
The only code that used it was the enumeration operations in AVM2.
2020-08-10 16:38:04 -07:00
David Wendt 4906c5a3f1 Remove uses of `as_string` in various places.
These include:

 * Name resolution in `newobject`
 * All runtime & late-bound multinames
 * `Object.hasOwnProperty`
 * `Object.propertyIsEnumerable`
 * `Object.setPropertyIsEnumerable`
2020-08-10 16:38:04 -07:00
David Wendt 962f6aa54c Remove `as_object`.
AVM2 is based on ES4, which as far as I'm aware, does not distinguish between "primitive values" and "objects". Thus, it is expedient to interpret any statement requiring something to be an Object to mean "not null or undefined".

Since we internally represent register values with primitive types, it is important that the VM always coerces to object before doing any other sort of type checking. Hence, something like `as_object` is unhelpful as it accidentally enforces a primitive/object distinction that ES4 attempted to remove.
2020-08-10 16:38:04 -07:00
David Wendt 8de063a916 Implement automatic primitive boxing via `coerce_to_object`. 2020-08-10 16:38:04 -07:00
David Wendt b7dfce51b8 Implement `greaterequals`, `greaterthan`, `lessequals`, and `lessthan`. 2020-08-10 16:38:04 -07:00
David Wendt 730c47cf29 Implement `ifge`, `ifgt`, `ifle`, `iflt`, `ifnge`, `ifngt`, `ifnle`, and `ifnlt`. 2020-08-10 16:38:04 -07:00
David Wendt 2ef03c6019 Allow no-hint primitive coercion 2020-08-10 16:38:04 -07:00
David Wendt 76ab8570e4 Implement and test `equals`.
The test is also far more in-depth than the `if_eq`/`if_ne` tests, which use the same set of vectors as the strict-equality tests from a while ago. Interestingly, this test passed on first run
2020-08-10 16:38:04 -07:00
David Wendt 29d5ae9989 Implement `ifeq` and `ifne`. 2020-08-10 16:38:04 -07:00
David Wendt 0125a14d1f Partially implement `ToObject` coercion.
Implementation is limited to generating exceptions on `null` or `undefined`. I'm not sure if primitive values don't exist in AVM2 or if this is supposed to box them like ES3, so I have decided to handle neither at this time.
2020-08-10 16:38:04 -07:00
David Wendt 0138300b5a Implement `coerce_s` and `convert_s`. 2020-08-10 16:38:04 -07:00
David Wendt 35f939cb15 Add and test for `convert_u` using `ToUint32` from ECMA-262 2020-08-10 16:38:04 -07:00
David Wendt 6eb41035cf Add & test ECMA-262 ToInt32 and `convert_i` opcode.
The ECMA-262 documentation is awfully overwrought for something that boils down to "chop off the non-whole part, wrap to 32 bits, then reinterpret as signed". Bitwise operations are *hell* to describe mathematically, and such descriptions are even harder to understand.
2020-08-10 16:38:04 -07:00
David Wendt 4c1489a814 Promote bytes to signed representation before pushing.
For whatever reason, `pushbyte` appears to be processed as a *signed* byte, despite the clear wording of "*byte_value* is an unsigned byte" in avm2overview.pdf. I guess it's supposed to be manually converted and promoted in this manner.
2020-08-10 16:38:04 -07:00
David Wendt 736a94a244 Implement numerical coercions according to ECMA-262 3rd Edition spec. 2020-08-10 16:38:04 -07:00
David Wendt 24fd30652d Allow tracing numbers to the console. 2020-08-10 16:38:04 -07:00
David Wendt 60f9613365 Implement and test for `convert_b`. 2020-08-10 16:38:04 -07:00
David Wendt 6cf48eb543 Implement and test `not`. 2020-08-10 16:38:04 -07:00
David Wendt 5bb8c1836f Replace `as_bool` with `coerce_to_bool`.
Functions that need to assert Boolness without coercion should either:

1. Ensure their function declaration requires a Boolean. (We don't enforce type errors on ES4 typehints yet, but we should.)
2. Check the value type themselves and raise their own errors if necessary.

As it stands the only users of `as_bool` either needed to check the type themselves or use `coerce_to_bool`. Notably, `setPropertyIsEnumerable` doesn't appear to coerce *or* throw an error: it instead fails silently if you hand it a non-`Boolean` value.
2020-08-10 16:38:04 -07:00
David Wendt 8ebf5405e2 Move AVM2 into the UpdateContext. 2020-08-01 15:49:29 -04:00
Nathan Adams 7f7281493f core: Allow toggling avm_debug output on and off with ctrl+alt+d, defaults to off 2020-07-23 19:14:32 -07:00
David Wendt 37b6b89d26 Add a stub AVM2 string representation to allow for both VMs' strings to diverge. 2020-07-18 16:20:58 -04:00
David Wendt f4c5075086 Run all string constant retrieval through the `TranslationUnit`, preventing us from making multiple copies of the same string.
For good measure, most of the other methods in `value` for retrieving pool primitives now also use `TranslationUnit` instead of `AbcFile`. This is the result of a handful of cascading changes throughout the project, and itself caused a few more.
2020-07-14 20:05:25 -04:00
David Wendt e1b9b823fc Remove `abc_string` and replace it with `abc_string_copy`. All code that pulls strings from the ABC file now uses `AvmString`s. 2020-07-13 23:41:46 -04:00
David Wendt 61a3ff8ae6 Replace `String` or `&str` references with `AvmString` everywhere in the AVM2 runtime. 2020-07-13 22:21:18 -04:00
David Wendt 508fcd6e9e `pool_string` should return a `Ref<str>` just like `value::abc_string`. 2020-07-13 17:45:12 -04:00
David Wendt a406bdada2 Don't attempt to log debugging information if we're not in a debug build. 2020-07-13 17:45:12 -04:00
David Wendt f0c633fe81 Allow borrowing string values from an ABC file instead of cloning everything. 2020-07-13 17:45:11 -04:00
David Wendt c917b3d411 Implement `istype`, `istypelate`, and `instanceof`. 2020-07-13 17:45:10 -04:00
David Wendt 8f2d3315f3 Allow the construction of classes with no base class.
This is primarily used for interfaces, in case you can't guess by the previous commit.
2020-07-13 17:45:07 -04:00
David Wendt 5d89d4ed85 Allow methods to not hold a body.
Interface methods are specifically not allowed to be called: as a result, they don't get a method body. Existing code assumed a 1:1 relationship between methods and bodies, which causes spurious errors.
2020-07-13 17:45:07 -04:00
David Wendt 090fe56bd3 Wrap `BytecodeMethod` (and the bytecode half of `Executable`) in a `Gc`.
This is inspired by Dinnerbone's similar PR on the AVM1 side, where the Action half of that VM's `Executable` was reduced from 128 bytes to 16 by shoving it in a `Gc`. This won't be as dramatic but should still save some memory.

In fact, it should save a *lot* of memory in bytecode execution, where thanks to the previous commit's rebase, we now need to clone the current method once *for each instruction executed*. That is terrible, but should stop now.
2020-07-13 17:45:06 -04:00
David Wendt 97e005622b Invert the role of `Avm2` and it's `Activation`, similar to what was done with `Avm1` and it's `Activation`.
This also results in a far reduced role for `ReturnValue`, since I also took the liberty of removing most of it's use. Furthermore, I also made it apply equally to native and AVM2 code, which ensures all native implementations of methods don't double-borrow.

In AVM1, `ReturnValue` was actually removed entirely, because it's not needed. I attempted to do the same, but the fact that we're currently embedding `ScriptObjectData` in native objects means that we need it for virtual properties. Otherwise, virtual property implementations will see locked objects, which is bad.
2020-07-13 17:45:06 -04:00
David Wendt 098b034de0 Refactor method-related structs into a separate method module.
This also renames `NativeFunction` and `Avm2MethodEntry` to `NativeMethod` and `BytecodeMethod`, respectively.
2020-07-13 17:45:05 -04:00
David Wendt 12fc13da7f Clippy compliance for the last batch of commits. 2020-07-13 17:45:05 -04:00
David Wendt eaebd3c63c Make `Avm2MethodEntry` hold it's `TranslationUnit` rather than an `AbcFile`. 2020-07-13 17:45:03 -04:00
David Wendt 60f3ae3ba7 Remove `Avm2ScriptEntry`. It is now obsolete and unused. 2020-07-13 17:45:02 -04:00
David Wendt f549d0146e Fix compilation bugs involved with automatic script initializer execution. 2020-07-13 17:45:02 -04:00
David Wendt 70e9030072 Decouple the entire trait machinery from ABC-provided traits.
This commit breaks the build: we still need to tell `Avm2` how to turn ABC traits into our own internal `Trait<'gc>`, `Class<'gc>`, and `Method<'gc>` types. We also need something to track which traits have already been instantiated, because `callstatic` would otherwise reinstantiate the trait in a different scope. (In fact, I think it *does* do exactly that right now...)
2020-07-13 17:45:01 -04:00
David Wendt 1b67bb94c8 Impl `callsuper`, `callsupervoid`, and `constructsuper`.
This works primarily by retaining the current superclass prototype in the activation object and then using it to retrieve the super method.

For constructors, we implement the `constructor` property, which is probably not the correct way to do this.
2020-07-13 17:44:15 -04:00
David Wendt a0ab978bed Impl `callmethod`, `callproperty`, `callproplex`, `callpropvoid`, and `callstatic`.
Also, implement a method table that method traits can optionally add themselves to.

Also also, add the ability to invoke a method without a `this` object. This required a non-trivial refactoring of the activation machinery, and changes to the signature of `NativeFunction`, and all native AVM2 functions.
2020-07-13 17:43:49 -04:00
David Wendt 9e120c216b Propagate arguments into local registers when calling AVM functions. 2020-07-13 17:43:44 -04:00
David Wendt 5b00c1fd96 Ensure that `this` is properly populated into local registers. 2020-07-13 17:43:44 -04:00
David Wendt 5f98a198cb Remove dead code in Activation 2020-07-13 17:43:41 -04:00
David Wendt 35c36a807b Always execute the last script when loading an ABC file 2020-07-13 17:43:23 -04:00
David Wendt eb0c9dcaec Allow constructing a function around a particular class definition.
I'm writing all this code assuming that classes and traits are syntactic sugar around ES3-style prototype chains on function objects. Hence, `FunctionObject` is still our workhorse object type for implementing typing.
2020-07-13 17:43:21 -04:00
David Wendt b12c6e0ff1 Implement closure scope stacks. 2020-07-13 17:43:20 -04:00