Skip to content

Commit

Permalink
Merge pull request #138 from buttercookie42/logicassign
Browse files Browse the repository at this point in the history
SpiderMonkey backports part 3 (logical assignment operators, fixes #118)
  • Loading branch information
MrAlex94 authored Jul 20, 2022
2 parents 87dfa7c + 01b37e2 commit 5edf390
Show file tree
Hide file tree
Showing 114 changed files with 11,912 additions and 4,765 deletions.
2 changes: 1 addition & 1 deletion js/public/CharacterEncoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class UTF8CharsZ : public mozilla::RangedPtr<unsigned char>
* to others. This differs from UTF8CharsZ in that the chars are
* const and it allows assignment.
*/
class ConstUTF8CharsZ
class JS_PUBLIC_API(ConstUTF8CharsZ)
{
const char* data_;

Expand Down
26 changes: 1 addition & 25 deletions js/src/builtin/Reflect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,6 @@ Reflect_deleteProperty(JSContext* cx, unsigned argc, Value* vp)
return true;
}

/* ES6 26.1.6 Reflect.get(target, propertyKey [, receiver]) */
static bool
Reflect_get(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);

// Step 1.
RootedObject obj(cx, NonNullObjectArg(cx, "`target`", "Reflect.get", args.get(0)));
if (!obj)
return false;

// Steps 2-3.
RootedValue propertyKey(cx, args.get(1));
RootedId key(cx);
if (!ToPropertyKey(cx, propertyKey, &key))
return false;

// Step 4.
RootedValue receiver(cx, args.length() > 2 ? args[2] : args.get(0));

// Step 5.
return GetProperty(cx, obj, receiver, key, args.rval());
}

/* ES6 26.1.8 Reflect.getPrototypeOf(target) */
bool
js::Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
Expand Down Expand Up @@ -210,7 +186,7 @@ static const JSFunctionSpec methods[] = {
JS_SELF_HOSTED_FN("construct", "Reflect_construct", 2, 0),
JS_SELF_HOSTED_FN("defineProperty", "Reflect_defineProperty", 3, 0),
JS_FN("deleteProperty", Reflect_deleteProperty, 2, 0),
JS_FN("get", Reflect_get, 2, 0),
JS_SELF_HOSTED_FN("get", "Reflect_get", 2, 0),
JS_SELF_HOSTED_FN("getOwnPropertyDescriptor", "Reflect_getOwnPropertyDescriptor", 2, 0),
JS_INLINABLE_FN("getPrototypeOf", Reflect_getPrototypeOf, 1, 0, ReflectGetPrototypeOf),
JS_SELF_HOSTED_FN("has", "Reflect_has", 2, 0),
Expand Down
22 changes: 21 additions & 1 deletion js/src/builtin/Reflect.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,30 @@ function Reflect_getOwnPropertyDescriptor(target, propertyKey) {
// 26.1.8 Reflect.has ( target, propertyKey )
function Reflect_has(target, propertyKey) {
// Step 1.
if (!IsObject(target))
if (!IsObject(target)) {
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_ARG, "`target`", "Reflect.has",
ToSource(target));
}

// Steps 2-3 are identical to the runtime semantics of the "in" operator.
return propertyKey in target;
}

// ES2018 draft rev 0525bb33861c7f4e9850f8a222c89642947c4b9c
// 26.1.5 Reflect.get ( target, propertyKey [ , receiver ] )
function Reflect_get(target, propertyKey/*, receiver*/) {
// Step 1.
if (!IsObject(target)) {
ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT_ARG, "`target`", "Reflect.get",
ToSource(target));
}

// Step 3 (reordered).
if (arguments.length > 2) {
// Steps 2, 4.
return getPropertySuper(target, propertyKey, arguments[2]);
}

// Steps 2, 4.
return target[propertyKey];
}
40 changes: 27 additions & 13 deletions js/src/builtin/ReflectParse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ enum AssignmentOperator {
AOP_LSH, AOP_RSH, AOP_URSH,
/* binary */
AOP_BITOR, AOP_BITXOR, AOP_BITAND,
/* short-circuit */
AOP_COALESCE, AOP_OR, AOP_AND,

AOP_LIMIT
};
Expand Down Expand Up @@ -116,19 +118,22 @@ enum PropKind {
};

static const char* const aopNames[] = {
"=", /* AOP_ASSIGN */
"+=", /* AOP_PLUS */
"-=", /* AOP_MINUS */
"*=", /* AOP_STAR */
"/=", /* AOP_DIV */
"%=", /* AOP_MOD */
"**=", /* AOP_POW */
"<<=", /* AOP_LSH */
">>=", /* AOP_RSH */
">>>=", /* AOP_URSH */
"|=", /* AOP_BITOR */
"^=", /* AOP_BITXOR */
"&=" /* AOP_BITAND */
"=", /* AOP_ASSIGN */
"+=", /* AOP_PLUS */
"-=", /* AOP_MINUS */
"*=", /* AOP_STAR */
"/=", /* AOP_DIV */
"%=", /* AOP_MOD */
"**=", /* AOP_POW */
"<<=", /* AOP_LSH */
">>=", /* AOP_RSH */
">>>=", /* AOP_URSH */
"|=", /* AOP_BITOR */
"^=", /* AOP_BITXOR */
"&=", /* AOP_BITAND */
"\?\?=", /* AOP_COALESCE */
"||=", /* AOP_OR */
"&&=", /* AOP_AND */
};

static const char* const binopNames[] = {
Expand Down Expand Up @@ -1919,6 +1924,12 @@ ASTSerializer::aop(ParseNodeKind kind)
return AOP_BITXOR;
case ParseNodeKind::BitAndAssign:
return AOP_BITAND;
case ParseNodeKind::CoalesceAssignExpr:
return AOP_COALESCE;
case ParseNodeKind::OrAssignExpr:
return AOP_OR;
case ParseNodeKind::AndAssignExpr:
return AOP_AND;
default:
return AOP_ERR;
}
Expand Down Expand Up @@ -2925,6 +2936,9 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
case ParseNodeKind::Assign:
case ParseNodeKind::AddAssign:
case ParseNodeKind::SubAssign:
case ParseNodeKind::CoalesceAssignExpr:
case ParseNodeKind::OrAssignExpr:
case ParseNodeKind::AndAssignExpr:
case ParseNodeKind::BitOrAssign:
case ParseNodeKind::BitXorAssign:
case ParseNodeKind::BitAndAssign:
Expand Down
9 changes: 7 additions & 2 deletions js/src/ds/InlineTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ template <typename InlineEntry,
typename HashPolicy,
typename AllocPolicy,
size_t InlineEntries>
class InlineTable
class InlineTable : private AllocPolicy
{
private:
using TablePtr = typename Table::Ptr;
Expand Down Expand Up @@ -103,7 +103,8 @@ class InlineTable
static const size_t SizeOfInlineEntries = sizeof(InlineEntry) * InlineEntries;

explicit InlineTable(AllocPolicy a = AllocPolicy())
: inlNext_(0),
: AllocPolicy(a),
inlNext_(0),
inlCount_(0),
table_(a)
{ }
Expand Down Expand Up @@ -304,6 +305,10 @@ class InlineTable

MOZ_ASSERT(!p.found());
MOZ_ASSERT(uintptr_t(inlineEnd()) == uintptr_t(p.inlAddPtr_));

if (!this->checkSimulatedOOM())
return false;

addPtr->update(mozilla::Forward<KeyInput>(key),
mozilla::Forward<Args>(args)...);
++inlCount_;
Expand Down
3 changes: 3 additions & 0 deletions js/src/ds/Nestable.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#ifndef ds_Nestable_h
#define ds_Nestable_h

#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"

namespace js {

// A base class for nestable structures.
Expand Down
101 changes: 101 additions & 0 deletions js/src/frontend/BytecodeControlStructures.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 "frontend/BytecodeControlStructures.h"

#include "frontend/BytecodeEmitter.h"
#include "frontend/EmitterScope.h"

using namespace js;
using namespace js::frontend;

NestableControl::NestableControl(BytecodeEmitter* bce, StatementKind kind)
: Nestable<NestableControl>(&bce->innermostNestableControl),
kind_(kind),
emitterScope_(bce->innermostEmitterScopeNoCheck())
{}

BreakableControl::BreakableControl(BytecodeEmitter* bce, StatementKind kind)
: NestableControl(bce, kind)
{
MOZ_ASSERT(is<BreakableControl>());
}

bool
BreakableControl::patchBreaks(BytecodeEmitter* bce)
{
return bce->emitJumpTargetAndPatch(breaks);
}

LabelControl::LabelControl(BytecodeEmitter* bce, JSAtom* label, ptrdiff_t startOffset)
: BreakableControl(bce, StatementKind::Label),
label_(bce->cx, label),
startOffset_(startOffset)
{}

LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
: BreakableControl(bce, loopKind),
tdzCache_(bce),
continueTarget({ -1 })
{
MOZ_ASSERT(is<LoopControl>());

LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());

stackDepth_ = bce->stackDepth;
loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;

int loopSlots;
if (loopKind == StatementKind::Spread) {
loopSlots = 3;
} else if (loopKind == StatementKind::ForInLoop || loopKind == StatementKind::ForOfLoop) {
loopSlots = 2;
} else {
loopSlots = 0;
}

MOZ_ASSERT(loopSlots <= stackDepth_);

if (enclosingLoop) {
canIonOsr_ = (enclosingLoop->canIonOsr_ &&
stackDepth_ == enclosingLoop->stackDepth_ + loopSlots);
} else {
canIonOsr_ = stackDepth_ == loopSlots;
}
}

bool
LoopControl::emitSpecialBreakForDone(BytecodeEmitter* bce)
{
// This doesn't pop stack values, nor handle any other controls.
// Should be called on the toplevel of the loop.
MOZ_ASSERT(bce->stackDepth == stackDepth_);
MOZ_ASSERT(bce->innermostNestableControl == this);

if (!bce->newSrcNote(SRC_BREAK))
return false;
if (!bce->emitJump(JSOP_GOTO, &breaks))
return false;

return true;
}

bool
LoopControl::patchBreaksAndContinues(BytecodeEmitter* bce)
{
MOZ_ASSERT(continueTarget.offset != -1);
if (!patchBreaks(bce))
return false;
bce->patchJumpsToTarget(continues, continueTarget);
return true;
}

TryFinallyControl::TryFinallyControl(BytecodeEmitter* bce, StatementKind kind)
: NestableControl(bce, kind),
emittingSubroutine_(false)
{
MOZ_ASSERT(is<TryFinallyControl>());
}
Loading

0 comments on commit 5edf390

Please sign in to comment.