Files
avmplus/shell/SystemClass.cpp
dmcallis 65a0592776 Initial source code drop
Source code drop for the Actionscript virtual machine in the Adobe
Flash Player for December 2013
2013-12-02 16:04:04 -08:00

341 lines
10 KiB
C++

/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "avmshell.h"
#include "Deopt.h"
namespace avmshell
{
SystemClass::SystemClass(avmplus::VTable *cvtable)
: avmplus::ClassClosure(cvtable)
{
ShellCore* core = (ShellCore*)this->core();
if (core->systemClass == NULL) {
core->systemClass = this;
}
createVanillaPrototype();
// initialTime: support for getTimer
// todo note this is currently routed to the performance counter
// for benchmark purposes.
#ifdef PERFORMANCE_GETTIMER
initialTime = VMPI_getPerformanceCounter();
#else
initialTime = VMPI_getTime();
#endif // PERFORMANCE_GETTIMER
}
SystemClass::~SystemClass()
{
initialTime = 0;
}
void SystemClass::exit(int status)
{
if (core()->getIsolate()->getAggregate()->isPrimordial(core()->getIsolate()->getDesc())) {
Platform::GetInstance()->exit(status);
} else {
GCRef<avmplus::ClassClosure> workerClass = toplevel()->workerClass();
static_cast<ShellWorkerClass*>((avmplus::ClassClosure*)workerClass)->getCurrentWorker()->terminate();
}
}
void SystemClass::sleep(int32_t ms)
{
// Or do we try to make the all the isolate threads sleep? In a safepoint? and interruptibly?
if (ms < 0)
ms = 0;
vmbase::VMThread::sleep(ms);
}
int SystemClass::exec(avmplus::Stringp command)
{
if (!command) {
toplevel()->throwArgumentError(kNullArgumentError, "command");
}
#ifdef UNDER_CE
AvmAssert(0);
return 0;
#else
avmplus::StUTF8String commandUTF8(command);
return system(commandUTF8.c_str());
#endif
}
avmplus::Stringp SystemClass::getAvmplusVersion()
{
return core()->newConstantStringLatin1(AVMPLUS_VERSION_USER " " AVMPLUS_BUILD_CODE);
}
avmplus::Stringp SystemClass::getFeatures()
{
return core()->newConstantStringLatin1(avmfeatures);
}
avmplus::Stringp SystemClass::getRunmode()
{
ShellCore* core = (ShellCore*)this->core();
if (core->config.runmode == avmplus::RM_mixed)
return core->newConstantStringLatin1("mixed");
if (core->config.runmode == avmplus::RM_jit_all)
{
if (core->config.jitordie)
return core->newConstantStringLatin1("jitordie");
return core->newConstantStringLatin1("jit");
}
if (core->config.runmode == avmplus::RM_interp_all)
return core->newConstantStringLatin1("interp");
return core->newConstantStringLatin1("unknown");
}
void SystemClass::write(avmplus::Stringp s)
{
if (!s)
toplevel()->throwArgumentError(kNullArgumentError, "string");
core()->console << s;
}
void SystemClass::trace(avmplus::ArrayObject* a)
{
if (!a)
toplevel()->throwArgumentError(kNullArgumentError, "array");
avmplus::AvmCore* core = this->core();
avmplus::PrintWriter& console = core->console;
for (int i=0, n = a->getLength(); i < n; i++)
{
if (i > 0)
console << ' ';
avmplus::StringIndexer s(core->string(a->getUintProperty(i)));
for (int j = 0; j < s->length(); j++)
{
wchar c = s[j];
// '\r' gets converted into '\n'
// '\n' is left alone
// '\r\n' is left alone
if (c == '\r')
{
if (((j+1) < s->length()) && s[j+1] == '\n')
{
console << '\r';
j++;
}
console << '\n';
}
else
{
console << c;
}
}
}
console << '\n';
}
void SystemClass::debugger()
{
#ifdef DEBUGGER
if (core()->debugger())
core()->debugger()->enterDebugger();
#endif
}
bool SystemClass::isDebugger()
{
#ifdef DEBUGGER
return core()->debugger() != NULL;
#else
return false;
#endif
}
unsigned SystemClass::getTimer()
{
#ifdef PERFORMANCE_GETTIMER
double time = ((double) (VMPI_getPerformanceCounter() - initialTime) * 1000.0 /
(double)VMPI_getPerformanceFrequency());
return (uint32_t)time;
#else
return (uint32_t)(VMPI_getTime() - initialTime);
#endif /* PERFORMANCE_GETTIMER */
}
double SystemClass::getNanosecondTimer()
{
return ((VMPI_getPerformanceCounter() - initialTime) * 1e9)
/ VMPI_getPerformanceFrequency();
}
int SystemClass::user_argc;
char **SystemClass::user_argv;
avmplus::ArrayObject * SystemClass::getArgv()
{
// get VTable for avmplus.System
avmplus::Toplevel *toplevel = this->toplevel();
avmplus::AvmCore *core = this->core();
avmplus::ArrayObject *array = toplevel->arrayClass()->newArray();
for(int i=0; i<user_argc;i++)
array->setUintProperty(i, core->newStringUTF8(user_argv[i])->atom());
return array;
}
avmplus::Stringp SystemClass::readLine()
{
avmplus::AvmCore* core = this->core();
avmplus::Stringp s = core->kEmptyString;
wchar wc[64];
int i=0;
for (int c = getchar(); c != '\n' && c != EOF; c = getchar())
{
wc[i++] = (wchar)c;
if (i == 63) {
wc[i] = 0;
s = s->append16(wc);
i = 0;
}
}
if (i > 0) {
wc[i] = 0;
s = s->append16(wc);
}
return s;
}
double SystemClass::get_totalMemory()
{
MMgc::GCHeap* gcheap = MMgc::GCHeap::GetGCHeap();
// Bugzilla 678975: use GetUsedHeapSize for compatibility with Player
return double(gcheap->GetUsedHeapSize() * MMgc::GCHeap::kBlockSize);
}
double SystemClass::get_freeMemory()
{
MMgc::GCHeap* gcheap = MMgc::GCHeap::GetGCHeap();
return double(gcheap->GetFreeHeapSize() * MMgc::GCHeap::kBlockSize);
}
double SystemClass::get_privateMemory()
{
return double(AVMPI_getPrivateResidentPageCount() * VMPI_getVMPageSize());
}
int32_t SystemClass::get_swfVersion()
{
ShellCore* core = (ShellCore*)this->core();
avmplus::BugCompatibility::Version v = core->getDefaultBugCompatibilityVersion();
AvmAssert(v >= 0 && v < avmplus::BugCompatibility::VersionCount);
return avmplus::BugCompatibility::kNames[v];
}
int32_t SystemClass::get_apiVersion()
{
ShellCore* core = (ShellCore*)this->core();
return core->defaultAPIVersion;
}
void SystemClass::forceFullCollection()
{
core()->GetGC()->Collect();
}
void SystemClass::queueCollection()
{
core()->GetGC()->QueueCollection();
}
bool SystemClass::isGlobal(avmplus::Atom o)
{
return avmplus::AvmCore::isObject(o) ? avmplus::AvmCore::atomToScriptObject(o)->isGlobalObject() : false;
}
void SystemClass::disposeXML(avmplus::XMLObject *xmlObject)
{
if(xmlObject)
xmlObject->dispose();
}
void SystemClass::pauseForGCIfCollectionImminent(double imminence)
{
if( avmplus::MathUtils::isNaN(imminence) )
imminence = 0.75;
core()->GetGC()->Collect(imminence);
}
void SystemClass::runInSafepoint(avmplus::FunctionObject* code)
{
class Task: public vmbase::SafepointTask {
avmplus::FunctionObject* m_code;
public:
Task(avmplus::FunctionObject* code): m_code(code) {}
void run() {
avmplus::Atom argv[] = {avmplus::nullObjectAtom};
m_code->call(0, argv);
}
};
Task task(code);
core()->getIsolate()->getAggregate()->safepointManager()->requestSafepointTask(task);
}
/*static*/ void FASTCALL CheckBaseClass::preCreateInstanceCheck(avmplus::ClassClosure* cls)
{
avmplus::Multiname qname(cls->traits()->ns(), cls->traits()->name());
// Deliberately throw a weird, non-sequitur error here so that we
// can distinguish this from construct="none" in the acceptance tests.
cls->toplevel()->argumentErrorClass()->throwError(kNotImplementedError, cls->core()->toErrorString(&qname));
}
bool SystemClass::is64bit()
{
#ifdef AVMPLUS_64BIT
return true;
#else
return false;
#endif
}
bool SystemClass::isIntptr(avmplus::Atom a)
{
return atomKind(a) == avmplus::AtomConstants::kIntptrType;
}
avmplus::Atom SystemClass::canonicalizeNumber(avmplus::Atom a)
{
if (atomKind(a) == avmplus::AtomConstants::kDoubleType) {
double val = *((double*)atomPtr(a));
intptr_t intval = intptr_t(val);
if (double(intval) == val && !(val == 0 && avmplus::MathUtils::isNegZero(val))) {
// Atom is double representing an integer value that will fit in intptr_t.
if (avmplus::atomIsValidIntptrValue(intval)) {
// The intptr_t value will also fit in kIntptrType atom, with tag.
return avmplus::atomFromIntptrValue(intval);
}
}
}
return a;
}
// Debug scaffolding for deoptimization.
// Deoptimize method invoked in frame K levels above our caller.
// Throws if no such frame exists, but is silently ignored if
// the method is not currently compiled.
void SystemClass::deopt(int32_t k)
{
#ifdef VMCFG_HALFMOON
using avmplus::Deoptimizer;
if (!Deoptimizer::deoptAncestor(core(), k))
toplevel()->throwArgumentError(kNullArgumentError, "frame number");
#endif
(void)k;
}
}