24 #include "nodes2bytecode.h"
25 #include <wtf/Assertions.h>
34 static void emitError(CompileState *comp,
Node *node, ErrorType type,
const char *msgStr)
36 OpValue me = OpValue::immNode(node);
37 OpValue se = OpValue::immInt32(type);
38 OpValue msg = OpValue::immCStr(msgStr);
39 CodeGen::emitOp(comp, Op_RaiseError,
nullptr, &me, &se, &msg);
42 static void emitSyntaxError(CompileState *comp,
Node *node,
const char *msgStr)
44 emitError(comp, node, SyntaxError, msgStr);
47 static void emitReferenceError(CompileState *comp,
Node *node,
const char *msgStr)
49 emitError(comp, node, ReferenceError, msgStr);
52 OpValue Node::generateEvalCode(CompileState *)
54 std::cerr <<
"WARNING: no generateEvalCode for:" <<
typeid(*this).name() <<
"\n";
57 return OpValue::immInt32(42);
60 void StatementNode::generateExecCode(CompileState *)
62 std::cerr <<
"WARNING: no generateExecCode for:" <<
typeid(*this).name() <<
"\n";
66 void StatementNode::generateDebugInfo(CompileState *comp)
68 OpValue me = OpValue::immNode(
this);
69 CodeGen::emitOp(comp, Op_AtStatement,
nullptr, &me);
72 static inline bool exitContextNeeded(CompileState *comp)
74 return comp->compileType() == Debug &&
75 comp->codeType() == FunctionCode;
78 static void generateExitContextIfNeeded(CompileState *comp)
80 if (exitContextNeeded(comp)) {
81 OpValue ourNode = OpValue::immNode(comp->functionBody());
82 CodeGen::emitOp(comp, Op_ExitDebugContext,
nullptr, &ourNode);
88 OpValue NullNode::generateEvalCode(CompileState *)
90 return OpValue::immValue(jsNull());
93 OpValue BooleanNode::generateEvalCode(CompileState *)
95 return OpValue::immBool(value());
98 OpValue NumberNode::generateEvalCode(CompileState *)
102 if (typeHint == OpType_Value) {
104 JSValue *im = JSImmediate::from(value());
106 OpValue res = mkImmediateVal(OpType_value);
114 int32_t i32 = JSValue::toInt32(d);
115 if (
double(i32) == d && !(i32 == 0 && signbit(d))) {
116 return OpValue::immInt32(i32);
118 return OpValue::immNumber(d);
122 OpValue StringNode::generateEvalCode(CompileState *comp)
130 return OpValue::immValue(interned);
134 if (val.size() < 16) {
135 interned = Interpreter::internString(val);
136 return OpValue::immValue(interned);
138 OpValue inStr = OpValue::immString(&val);
141 CodeGen::emitOp(comp, Op_OwnedString, &out, &inStr);
146 StringNode::~StringNode()
149 Interpreter::releaseInternedString(val);
153 OpValue RegExpNode::generateEvalCode(CompileState *comp)
157 OpValue patternV = OpValue::immString(&pattern);
158 OpValue flagsV = OpValue::immString(&flags);
159 CodeGen::emitOp(comp, Op_NewRegExp, &out, &patternV, &flagsV);
163 OpValue ThisNode::generateEvalCode(CompileState *comp)
165 return *comp->thisValue();
170 size_t VarAccessNode::classifyVariable(CompileState *comp, Classification &classify)
177 if (comp->inNestedScope() || comp->codeType() == EvalCode) {
179 return missingSymbolMarker();
184 if (comp->codeType() == GlobalCode) {
186 return missingSymbolMarker();
190 if (ident == CommonIdentifiers::shared()->arguments) {
193 return missingSymbolMarker();
197 size_t index = comp->functionBody()->lookupSymbolID(ident);
198 if (index == missingSymbolMarker()) {
207 OpValue VarAccessNode::generateEvalCode(CompileState *comp)
209 Classification classify;
210 size_t index = classifyVariable(comp, classify);
213 OpValue varName = OpValue::immIdent(&ident);
217 out = comp->localReadVal(index);
221 CodeGen::emitOp(comp, Op_NonLocalVarGet, &out, &varName);
224 CodeGen::emitOp(comp, Op_GlobalObjectGet, &out, &varName);
227 CodeGen::emitOp(comp, Op_VarGet, &out, &varName);
234 OpValue VarAccessNode::valueForTypeOf(CompileState *comp)
237 Classification classify;
238 size_t index = classifyVariable(comp, classify);
242 OpValue varName = OpValue::immIdent(&ident);
246 out = comp->localReadVal(index);
249 CodeGen::emitOp(comp, Op_SymGetKnownObject, &out, comp->globalScope(), &varName);
252 comp->requestTemporary(OpType_value, &out, &outReg);
253 CodeGen::emitOp(comp, Op_NonLocalScopeLookupAndGet, &scopeTemp, &outReg, &varName);
256 comp->requestTemporary(OpType_value, &out, &outReg);
257 CodeGen::emitOp(comp, Op_ScopeLookupAndGet, &scopeTemp, &outReg, &varName);
264 CompileReference *VarAccessNode::generateRefBind(CompileState *comp)
266 Classification classify;
267 classifyVariable(comp, classify);
269 if (classify == Local || classify == Global) {
274 CompileReference *
ref =
new CompileReference;
276 OpValue quiet = OpValue::immNode(
nullptr);
277 OpValue varName = OpValue::immIdent(&ident);
278 CodeGen::emitOp(comp, classify == Dynamic ? Op_ScopeLookup : Op_NonLocalScopeLookup,
279 &
ref->baseObj, &varName, &quiet);
283 CompileReference *VarAccessNode::generateRefRead(CompileState *comp, OpValue *out)
285 Classification classify;
286 classifyVariable(comp, classify);
291 if (classify == Local || classify == Global) {
292 *out = generateEvalCode(comp);
297 CompileReference *
ref =
new CompileReference;
300 OpValue varName = OpValue::immIdent(&ident);
301 comp->requestTemporary(OpType_value, out, &readReg);
304 if (classify == Dynamic) {
305 op = Op_ScopeLookupAndGetChecked;
307 op = Op_NonLocalScopeLookupAndGetChecked;
309 CodeGen::emitOp(comp, op, &
ref->baseObj, &readReg, &varName);
314 void VarAccessNode::generateRefWrite(CompileState *comp,
315 CompileReference *ref, OpValue &valToStore)
317 Classification classify;
318 size_t index = classifyVariable(comp, classify);
320 if (classify == Local) {
322 OpValue destReg = comp->localWriteRef(comp->codeBlock(), index);
323 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, &destReg, &valToStore);
326 OpValue varName = OpValue::immIdent(&ident);
327 CodeGen::emitOp(comp, Op_SymPutKnownObject,
nullptr,
328 (classify == Global ? comp->globalScope() : &
ref->baseObj), &varName, &valToStore);
332 OpValue VarAccessNode::generateRefDelete(CompileState *comp)
334 Classification classify;
335 classifyVariable(comp, classify);
337 if (classify == Local) {
339 return OpValue::immBool(
false);
344 if (classify == Global) {
345 base = *comp->globalScope();
347 OpValue varName = OpValue::immIdent(&ident);
348 OpValue silent = OpValue::immNode(
nullptr);
349 CodeGen::emitOp(comp, classify == Dynamic ? Op_ScopeLookup : Op_NonLocalScopeLookup,
350 &base, &varName, &silent);
355 OpValue varName = OpValue::immIdent(&ident);
356 CodeGen::emitOp(comp, Op_SymDeleteKnownObject, &out, &base, &varName);
360 void VarAccessNode::generateRefFunc(CompileState *comp, OpValue *funOut, OpValue *thisOut)
362 Classification classify;
363 classifyVariable(comp, classify);
365 OpValue varName = OpValue::immIdent(&ident);
372 *funOut = generateEvalCode(comp);
373 *thisOut = *comp->globalScope();
376 comp->requestTemporary(OpType_value, thisOut, &thisReg);
377 CodeGen::emitOp(comp, Op_NonLocalFunctionLookupAndGet, funOut, &thisReg, &varName);
380 comp->requestTemporary(OpType_value, thisOut, &thisReg);
381 CodeGen::emitOp(comp, Op_FunctionLookupAndGet, funOut, &thisReg, &varName);
388 OpValue GroupNode::generateEvalCode(CompileState *comp)
390 return group->generateEvalCode(comp);
395 OpValue ArrayNode::generateEvalCode(CompileState *comp)
398 CodeGen::emitOp(comp, Op_NewEmptyArray, &arr);
400 OpValue und = OpValue::immValue(jsUndefined());
403 for (ElementNode *el = element.get(); el; el = el->next.get()) {
406 for (
int i = 0; i < el->elision; i++) {
407 OpValue ind = OpValue::immInt32(pos);
408 CodeGen::emitOp(comp, Op_BracketPutKnownObject,
nullptr, &arr, &ind, &und);
416 OpValue val = el->node->generateEvalCode(comp);
417 OpValue ind = OpValue::immInt32(pos);
418 CodeGen::emitOp(comp, Op_BracketPutKnownObject,
nullptr, &arr, &ind, &val);
423 for (
int i = 0; i < elision; i++) {
424 OpValue ind = OpValue::immInt32(pos);
425 CodeGen::emitOp(comp, Op_BracketPutKnownObject,
nullptr, &arr, &ind, &und);
432 OpValue ObjectLiteralNode::generateEvalCode(CompileState *comp)
435 CodeGen::emitOp(comp, Op_NewObject, &obj);
437 for (PropertyListNode *entry =
list.get(); entry; entry = entry->next.get()) {
438 PropertyNode *prop = entry->node.get();
439 OpValue
name = OpValue::immIdent(&prop->name->str);
440 OpValue val = prop->assign->generateEvalCode(comp);
442 switch (prop->type) {
443 case PropertyNode::Getter:
444 CodeGen::emitOp(comp, Op_DefineGetter,
nullptr, &obj, &name, &val);
446 case PropertyNode::Setter:
447 CodeGen::emitOp(comp, Op_DefineSetter,
nullptr, &obj, &name, &val);
449 case PropertyNode::Constant:
450 CodeGen::emitOp(comp, Op_SymPutKnownObject,
nullptr, &obj, &name, &val);
459 OpValue BracketAccessorNode::generateEvalCode(CompileState *comp)
462 OpValue base = expr1->generateEvalCode(comp);
463 OpValue index = expr2->generateEvalCode(comp);
466 CodeGen::emitOp(comp, Op_BracketGet, &ret, &base, &index);
470 CompileReference *BracketAccessorNode::generateRefBind(CompileState *comp)
479 CompileReference *
ref =
new CompileReference;
480 OpValue baseV = expr1->generateEvalCode(comp);
481 ref->indexVal = expr2->generateEvalCode(comp);
482 CodeGen::emitOp(comp, Op_ToObject, &
ref->baseObj, &baseV);
486 CompileReference *BracketAccessorNode::generateRefRead(CompileState *comp, OpValue *out)
488 CompileReference *
ref =
new CompileReference;
492 OpValue baseV = expr1->generateEvalCode(comp);
493 ref->indexVal = expr2->generateEvalCode(comp);
497 comp->requestTemporary(OpType_value, &
ref->baseObj, &baseReg);
499 CodeGen::emitOp(comp, Op_BracketGetAndBind, out, &baseReg, &baseV, &
ref->indexVal);
503 void BracketAccessorNode::generateRefWrite(CompileState *comp,
504 CompileReference *ref, OpValue &valToStore)
506 CodeGen::emitOp(comp, Op_BracketPutKnownObject,
nullptr, &
ref->baseObj, &
ref->indexVal, &valToStore);
509 OpValue BracketAccessorNode::generateRefDelete(CompileState *comp)
511 OpValue base = expr1->generateEvalCode(comp);
512 OpValue index = expr2->generateEvalCode(comp);
515 CodeGen::emitOp(comp, Op_BracketDelete, &out, &base, &index);
519 void BracketAccessorNode::generateRefFunc(CompileState *comp, OpValue *funOut, OpValue *thisOut)
521 OpValue baseV = expr1->generateEvalCode(comp);
522 OpValue indexV = expr2->generateEvalCode(comp);
526 comp->requestTemporary(OpType_value, thisOut, &baseReg);
528 CodeGen::emitOp(comp, Op_BracketGetAndBind, funOut, &baseReg, &baseV, &indexV);
534 OpValue DotAccessorNode::generateEvalCode(CompileState *comp)
537 OpValue base = expr->generateEvalCode(comp);
538 OpValue varName = OpValue::immIdent(&ident);
539 CodeGen::emitOp(comp, Op_SymGet, &ret, &base, &varName);
543 CompileReference *DotAccessorNode::generateRefBind(CompileState *comp)
545 CompileReference *
ref =
new CompileReference;
546 OpValue baseV = expr->generateEvalCode(comp);
547 CodeGen::emitOp(comp, Op_ToObject, &
ref->baseObj, &baseV);
551 CompileReference *DotAccessorNode::generateRefRead(CompileState *comp, OpValue *out)
553 CompileReference *
ref =
new CompileReference;
554 OpValue baseV = expr->generateEvalCode(comp);
556 OpValue varName = OpValue::immIdent(&ident);
557 comp->requestTemporary(OpType_value, &
ref->baseObj, &baseReg);
558 CodeGen::emitOp(comp, Op_SymGetAndBind, out, &baseReg, &baseV, &varName);
562 void DotAccessorNode::generateRefWrite(CompileState *comp,
563 CompileReference *ref, OpValue &valToStore)
565 OpValue varName = OpValue::immIdent(&ident);
566 CodeGen::emitOp(comp, Op_SymPutKnownObject,
nullptr, &
ref->baseObj, &varName, &valToStore);
569 OpValue DotAccessorNode::generateRefDelete(CompileState *comp)
571 OpValue base = expr->generateEvalCode(comp);
572 OpValue varName = OpValue::immIdent(&ident);
574 CodeGen::emitOp(comp, Op_SymDelete, &out, &base, &varName);
578 void DotAccessorNode::generateRefFunc(CompileState *comp, OpValue *funOut, OpValue *thisOut)
580 OpValue baseV = expr->generateEvalCode(comp);
581 OpValue varName = OpValue::immIdent(&ident);
584 comp->requestTemporary(OpType_value, thisOut, &baseReg);
585 CodeGen::emitOp(comp, Op_SymGetAndBind, funOut, &baseReg, &baseV, &varName);
590 void ArgumentsNode::generateEvalArguments(CompileState *comp)
592 WTF::Vector<OpValue> args;
596 for (ArgumentListNode *arg =
list.get(); arg; arg = arg->next.get()) {
597 args.append(arg->expr->generateEvalCode(comp));
600 CodeGen::emitOp(comp, Op_ClearArgs,
nullptr);
603 while (c < args.size()) {
604 if (c + 3 <= args.size()) {
605 CodeGen::emitOp(comp, Op_Add3Arg,
nullptr, &args[c], &args[c + 1], &args[c + 2]);
607 }
else if (c + 2 <= args.size()) {
608 CodeGen::emitOp(comp, Op_Add2Arg,
nullptr, &args[c], &args[c + 1]);
611 CodeGen::emitOp(comp, Op_AddArg,
nullptr, &args[c]);
617 OpValue NewExprNode::generateEvalCode(CompileState *comp)
619 OpValue v = expr->generateEvalCode(comp);
622 args->generateEvalArguments(comp);
624 CodeGen::emitOp(comp, Op_ClearArgs,
nullptr);
628 CodeGen::emitOp(comp, Op_CtorCall, &out, &v);
632 OpValue FunctionCallValueNode::generateEvalCode(CompileState *comp)
634 OpValue v = expr->generateEvalCode(comp);
635 args->generateEvalArguments(comp);
638 CodeGen::emitOp(comp, Op_FunctionCall, &out, &v, comp->globalScope());
642 OpValue FunctionCallReferenceNode::generateEvalCode(CompileState *comp)
644 Node *cand = expr->nodeInsideAllParens();
645 ASSERT(cand->isLocation());
646 LocationNode *loc =
static_cast<LocationNode *
>(cand);
648 OpValue funVal, thisVal;
649 loc->generateRefFunc(comp, &funVal, &thisVal);
650 args->generateEvalArguments(comp);
653 CodeGen::emitOp(comp, Op_FunctionCall, &out, &funVal, &thisVal);
657 OpValue PostfixNode::generateEvalCode(CompileState *comp)
659 Node *cand = m_loc->nodeInsideAllParens();
660 if (!cand->isLocation()) {
661 emitReferenceError(comp,
this,
662 m_oper == OpPlusPlus ?
663 "Postfix ++ operator applied to value that is not a reference." :
664 "Postfix -- operator applied to value that is not a reference.");
665 return OpValue::immValue(jsUndefined());
668 LocationNode *loc =
static_cast<LocationNode *
>(cand);
674 CompileReference *
ref = loc->generateRefRead(comp, &curV);
677 if (curV.type != OpType_number) {
679 CodeGen::emitConvertTo(comp, &curV, OpType_number, &numVal);
685 CodeGen::emitOp(comp, (m_oper == OpPlusPlus) ? Op_Add1 : Op_Sub1,
688 loc->generateRefWrite(comp, ref, newV);
693 OpValue DeleteReferenceNode::generateEvalCode(CompileState *comp)
695 return loc->generateRefDelete(comp);
698 OpValue DeleteValueNode::generateEvalCode(CompileState *)
700 return OpValue::immBool(
true);
703 OpValue VoidNode::generateEvalCode(CompileState *comp)
705 (void)expr->generateEvalCode(comp);
706 return OpValue::immValue(jsUndefined());
709 OpValue TypeOfVarNode::generateEvalCode(CompileState *comp)
711 OpValue v = loc->valueForTypeOf(comp);
714 CodeGen::emitOp(comp, Op_TypeOf, &out, &v);
718 OpValue TypeOfValueNode::generateEvalCode(CompileState *comp)
720 OpValue v = m_expr->generateEvalCode(comp);
722 CodeGen::emitOp(comp, Op_TypeOf, &typeOfV, &v);
726 OpValue PrefixNode::generateEvalCode(CompileState *comp)
728 Node *cand = m_loc->nodeInsideAllParens();
729 if (!cand->isLocation()) {
730 emitReferenceError(comp,
this,
731 m_oper == OpPlusPlus ?
732 "Prefix ++ operator applied to value that is not a reference." :
733 "Prefix -- operator applied to value that is not a reference.");
734 return OpValue::immValue(jsUndefined());
737 LocationNode *loc =
static_cast<LocationNode *
>(cand);
743 CompileReference *
ref = loc->generateRefRead(comp, &curV);
746 CodeGen::emitOp(comp, (m_oper == OpPlusPlus) ? Op_Add1 : Op_Sub1,
750 loc->generateRefWrite(comp, ref, newV);
755 OpValue UnaryPlusNode::generateEvalCode(CompileState *comp)
758 OpValue curV = expr->generateEvalCode(comp);
760 if (curV.type != OpType_number) {
762 CodeGen::emitConvertTo(comp, &curV, OpType_number, &numVal);
769 OpValue NegateNode::generateEvalCode(CompileState *comp)
771 OpValue v = expr->generateEvalCode(comp);
773 CodeGen::emitOp(comp, Op_Neg, &negV, &v);
777 OpValue BitwiseNotNode::generateEvalCode(CompileState *comp)
779 OpValue v = expr->generateEvalCode(comp);
781 CodeGen::emitOp(comp, Op_BitNot, &out, &v);
785 OpValue LogicalNotNode::generateEvalCode(CompileState *comp)
787 OpValue v = expr->generateEvalCode(comp);
789 CodeGen::emitOp(comp, Op_LogicalNot, &out, &v);
793 OpValue BinaryOperatorNode::generateEvalCode(CompileState *comp)
795 OpValue v1 = expr1->generateEvalCode(comp);
796 OpValue v2 = expr2->generateEvalCode(comp);
843 codeOp = Op_GreaterEq;
885 codeOp = Op_InstanceOf;
889 codeOp = Op_InstanceOf;
890 assert(!
"BinaryOperatorNode: unhandled switch case");
894 CodeGen::emitOp(comp, codeOp, &out, &v1, &v2);
898 OpValue BinaryLogicalNode::generateEvalCode(CompileState *comp)
904 OpValue a = expr1->generateEvalCode(comp);
908 comp->requestTemporary(a.type, &aVal, &aReg);
909 CodeGen::emitRegStore(comp, &aReg, &a);
914 Addr jumpToShortCircuit = CodeGen::emitOp(comp, oper == OpAnd ? Op_IfNotJump : Op_IfJump,
915 nullptr, &a, OpValue::dummyAddr());
918 OpValue b = expr2->generateEvalCode(comp);
922 if (a.type == b.type || a.type == OpType_value) {
923 if (a.type == OpType_value) {
924 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, &aReg, &b);
926 CodeGen::emitRegStore(comp, &aReg, &b);
928 CodeGen::patchJumpToNext(comp, jumpToShortCircuit, 1);
935 OpValue resVal, resReg;
936 comp->requestTemporary(OpType_value, &resVal, &resReg);
937 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, &resReg, &b);
940 Addr jumpToAfter = CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
943 CodeGen::patchJumpToNext(comp, jumpToShortCircuit, 1);
944 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, &resReg, &a);
947 CodeGen::patchJumpToNext(comp, jumpToAfter, 0);
953 OpValue ConditionalNode::generateEvalCode(CompileState *comp)
958 OpValue resVal, resReg;
961 OpValue v = logical->generateEvalCode(comp);
962 Addr jumpToElse = CodeGen::emitOp(comp, Op_IfNotJump,
nullptr, &v, OpValue::dummyAddr());
965 OpValue v1out = expr1->generateEvalCode(comp);
969 comp->requestTemporary(OpType_value, &resVal, &resReg);
970 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, &resReg, &v1out);
972 Addr jumpToAfter = CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
975 CodeGen::patchJumpToNext(comp, jumpToElse, 1);
978 OpValue v2out = expr2->generateEvalCode(comp);
979 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, &resReg, &v2out);
982 CodeGen::patchJumpToNext(comp, jumpToAfter, 0);
987 OpValue FuncExprNode::generateEvalCode(CompileState *comp)
989 comp->setNeedsClosures();
992 OpValue nameV = OpValue::immIdent(&ident);
993 OpValue bodyV = OpValue::immNode(body.get());
994 CodeGen::emitOp(comp, Op_EvalFuncExpr, &out, &nameV, &bodyV);
998 void FuncDeclNode::generateExecCode(CompileState *comp)
1000 comp->setNeedsClosures();
1005 void SourceElementsNode::generateExecCode(CompileState *comp)
1007 node->generateExecCode(comp);
1010 for (SourceElementsNode *n =
next.get(); n; n = n->next.get()) {
1011 n->node->generateExecCode(comp);
1015 OpValue AssignNode::generateEvalCode(CompileState *comp)
1017 Node *cand = m_loc->nodeInsideAllParens();
1018 if (!cand->isLocation()) {
1019 emitReferenceError(comp,
this,
"Left side of assignment is not a reference.");
1020 return OpValue::immValue(jsUndefined());
1023 LocationNode *loc =
static_cast<LocationNode *
>(cand);
1025 CompileReference *
ref;
1028 if (m_oper == OpEqual) {
1029 ref = loc->generateRefBind(comp);
1030 v = m_right->generateEvalCode(comp);
1033 ref = loc->generateRefRead(comp, &v1);
1034 OpValue v2 = m_right->generateEvalCode(comp);
1063 codeOp = Op_URShift;
1079 CodeGen::emitOp(comp, codeOp, &v, &v1, &v2);
1082 loc->generateRefWrite(comp, ref, v);
1088 OpValue CommaNode::generateEvalCode(CompileState *comp)
1090 expr1->generateEvalCode(comp);
1091 return expr2->generateEvalCode(comp);
1094 OpValue AssignExprNode::generateEvalCode(CompileState *comp)
1096 return expr->generateEvalCode(comp);
1099 void VarDeclNode::generateCode(CompileState *comp)
1105 if (comp->inNestedScope()) {
1107 OpValue quiet = OpValue::immNode(
nullptr);
1108 OpValue varName = OpValue::immIdent(&ident);
1110 CodeGen::emitOp(comp, Op_ScopeLookup, &base, &varName, &quiet);
1112 OpValue val =
init->generateEvalCode(comp);
1113 CodeGen::emitOp(comp, Op_SymPutKnownObject,
nullptr, &base, &varName, &val);
1117 OpValue val =
init->generateEvalCode(comp);
1118 size_t localID = comp->functionBody()->lookupSymbolID(ident);
1119 if (localID == missingSymbolMarker()) {
1121 OpValue identV = OpValue::immIdent(&ident);
1122 CodeGen::emitOp(comp, Op_SymPutKnownObject,
nullptr, comp->localScope(), &identV, &val);
1125 OpValue dest = comp->localWriteRef(comp->codeBlock(), localID);
1126 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, &dest, &val);
1131 OpValue VarDeclListNode::generateEvalCode(CompileState *comp)
1133 for (VarDeclListNode *n =
this; n; n = n->next.get()) {
1134 n->var->generateCode(comp);
1137 return OpValue::immInt32(0);
1140 void VarStatementNode::generateExecCode(CompileState *comp)
1142 generateDebugInfoIfNeeded(comp);
1143 next->generateEvalCode(comp);
1146 void BlockNode::generateExecCode(CompileState *comp)
1149 generateDebugInfoIfNeeded(comp);
1150 source->generateExecCode(comp);
1154 void EmptyStatementNode::generateExecCode(CompileState *)
1157 void ExprStatementNode::generateExecCode(CompileState *comp)
1159 generateDebugInfoIfNeeded(comp);
1160 OpValue val = expr->generateEvalCode(comp);
1163 if (comp->codeType() != FunctionCode) {
1164 CodeGen::emitOp(comp, Op_RegPutValue,
nullptr, comp->evalResultReg(), &val);
1168 void IfNode::generateExecCode(CompileState *comp)
1170 generateDebugInfoIfNeeded(comp);
1173 OpValue cond = expr->generateEvalCode(comp);
1176 Addr afterTrueJmp = CodeGen::emitOp(comp, Op_IfNotJump,
nullptr, &cond, OpValue::dummyAddr());
1179 statement1->generateExecCode(comp);
1182 Addr afterAllJmp = 0;
1184 afterAllJmp = CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
1188 CodeGen::patchJumpToNext(comp, afterTrueJmp, 1);
1192 statement2->generateExecCode(comp);
1195 CodeGen::patchJumpToNext(comp, afterAllJmp, 0);
1199 void DoWhileNode::generateExecCode(CompileState *comp)
1201 generateDebugInfoIfNeeded(comp);
1202 comp->enterLoop(
this);
1205 OpValue beforeBody = OpValue::immAddr(CodeGen::nextPC(comp));
1206 statement->generateExecCode(comp);
1209 comp->resolvePendingContinues(
this, CodeGen::nextPC(comp));
1212 OpValue cond = expr->generateEvalCode(comp);
1213 CodeGen::emitOp(comp, Op_IfJump,
nullptr, &cond, &beforeBody);
1215 comp->exitLoop(
this);
1218 void WhileNode::generateExecCode(CompileState *comp)
1220 generateDebugInfoIfNeeded(comp);
1221 comp->enterLoop(
this);
1224 Addr jumpToTest = CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
1227 OpValue beforeBody = OpValue::immAddr(CodeGen::nextPC(comp));
1228 statement->generateExecCode(comp);
1231 comp->resolvePendingContinues(
this, CodeGen::nextPC(comp));
1234 CodeGen::patchJumpToNext(comp, jumpToTest, 0);
1237 OpValue cond = expr->generateEvalCode(comp);
1238 CodeGen::emitOp(comp, Op_IfJump,
nullptr, &cond, &beforeBody);
1240 comp->exitLoop(
this);
1243 void ForNode::generateExecCode(CompileState *comp)
1245 generateDebugInfoIfNeeded(comp);
1246 comp->enterLoop(
this);
1250 expr1->generateEvalCode(comp);
1254 Addr jumpToTest = CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
1257 OpValue bodyAddr = OpValue::immAddr(CodeGen::nextPC(comp));
1258 statement->generateExecCode(comp);
1261 comp->resolvePendingContinues(
this, CodeGen::nextPC(comp));
1265 expr3->generateEvalCode(comp);
1269 CodeGen::patchJumpToNext(comp, jumpToTest, 0);
1273 OpValue cond = expr2->generateEvalCode(comp);
1274 CodeGen::emitOp(comp, Op_IfJump,
nullptr, &cond, &bodyAddr);
1277 CodeGen::emitOp(comp, Op_Jump,
nullptr, &bodyAddr);
1280 comp->exitLoop(
this);
1283 void ForInNode::generateExecCode(CompileState *comp)
1285 generateDebugInfoIfNeeded(comp);
1287 varDecl->generateCode(comp);
1290 OpValue val = expr->generateEvalCode(comp);
1293 OpValue stateVal, stateReg;
1294 comp->requestTemporary(OpType_value, &stateVal, &stateReg);
1297 CodeGen::emitOp(comp, Op_BeginForIn, &obj, &val, &stateReg);
1299 comp->enterLoop(
this);
1303 Addr fetchNext = CodeGen::emitOp(comp, Op_NextForInEntry, &sym, &obj,
1304 &stateVal, OpValue::dummyAddr());
1307 assert(lexpr->isLocation());
1308 LocationNode *loc =
static_cast<LocationNode *
>(lexpr.get());
1310 CompileReference *
ref = loc->generateRefBind(comp);
1311 loc->generateRefWrite(comp, ref, sym);
1315 statement->generateExecCode(comp);
1318 comp->resolvePendingContinues(
this, fetchNext);
1321 OpValue backVal = OpValue::immAddr(fetchNext);
1322 CodeGen::emitOp(comp, Op_Jump,
nullptr, &backVal);
1325 CodeGen::patchJumpToNext(comp, fetchNext, 3);
1327 comp->exitLoop(
this);
1332 static void handleJumpOut(CompileState *comp,
Node *dest, ComplType breakOrCont)
1338 const WTF::Vector<CompileState::NestInfo> &nests = comp->nestStack();
1340 for (
int pos = nests.size() - 1; pos >= 0; --pos) {
1341 switch (nests[pos].type) {
1342 case CompileState::Scope:
1343 case CompileState::OtherCleanup:
1346 case CompileState::TryFinally: {
1349 Addr pc = CodeGen::nextPC(comp);
1350 CodeGen::emitOp(comp, Op_ContBreakInTryFinally,
nullptr, OpValue::dummyAddr());
1353 if (breakOrCont == Continue) {
1354 comp->addPendingContinue(dest, pc);
1356 comp->addPendingBreak(dest, pc);
1362 case CompileState::ContBreakTarget:
1363 if (nests[pos].node == dest) {
1367 OpValue unwind = OpValue::immInt32(toUnwind);
1368 CodeGen::emitOp(comp, Op_UnwindStacks,
nullptr, &unwind);
1372 Addr pc = CodeGen::nextPC(comp);
1373 CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
1376 if (breakOrCont == Continue) {
1377 comp->addPendingContinue(dest, pc);
1379 comp->addPendingBreak(dest, pc);
1387 assert(!
"Huh? Unable to find continue/break target in the nest stack");
1390 void ContinueNode::generateExecCode(CompileState *comp)
1392 generateDebugInfoIfNeeded(comp);
1393 Node *dest = comp->resolveContinueLabel(ident);
1395 if (ident.isEmpty()) {
1396 emitSyntaxError(comp,
this,
"Illegal continue without target outside a loop.");
1398 emitSyntaxError(comp,
this,
"Invalid label in continue.");
1402 if (dest->isIterationStatement()) {
1403 handleJumpOut(comp, dest, Continue);
1405 emitSyntaxError(comp,
this,
"Invalid continue target; must be a loop.");
1410 void BreakNode::generateExecCode(CompileState *comp)
1412 generateDebugInfoIfNeeded(comp);
1413 Node *dest = comp->resolveBreakLabel(ident);
1415 if (ident.isEmpty()) {
1416 emitSyntaxError(comp,
this,
"Illegal break without target outside a loop or switch.");
1418 emitSyntaxError(comp,
this,
"Invalid label in break.");
1421 handleJumpOut(comp, dest, Break);
1425 void ReturnNode::generateExecCode(CompileState *comp)
1427 generateDebugInfoIfNeeded(comp);
1431 if (comp->codeType() != FunctionCode) {
1432 emitSyntaxError(comp,
this,
"Invalid return.");
1437 arg = OpValue::immValue(jsUndefined());
1439 arg = value->generateEvalCode(comp);
1442 if (!comp->inTryFinally()) {
1443 generateExitContextIfNeeded(comp);
1446 CodeGen::emitOp(comp, comp->inTryFinally() ? Op_ReturnInTryFinally : Op_Return,
nullptr, &arg);
1449 void WithNode::generateExecCode(CompileState *comp)
1451 generateDebugInfoIfNeeded(comp);
1454 comp->setNeedsClosures();
1456 OpValue scopeObj = expr->generateEvalCode(comp);
1458 comp->pushNest(CompileState::Scope,
this);
1459 CodeGen::emitOp(comp, Op_PushScope,
nullptr, &scopeObj);
1461 statement->generateExecCode(comp);
1463 CodeGen::emitOp(comp, Op_PopScope,
nullptr);
1467 void LabelNode::generateExecCode(CompileState *comp)
1469 if (!comp->pushLabel(label)) {
1470 emitSyntaxError(comp,
this,
"Duplicated label found.");
1474 if (!statement->isLabelNode()) {
1475 comp->pushNest(CompileState::ContBreakTarget, statement.get());
1476 comp->bindLabels(statement.get());
1480 statement->generateExecCode(comp);
1483 if (!statement->isLabelNode()) {
1485 comp->resolvePendingBreaks(statement.get(), CodeGen::nextPC(comp));
1491 void ThrowNode::generateExecCode(CompileState *comp)
1493 generateDebugInfoIfNeeded(comp);
1494 OpValue projectile = expr->generateEvalCode(comp);
1495 CodeGen::emitOp(comp, Op_Throw,
nullptr, &projectile);
1498 void TryNode::generateExecCode(CompileState *comp)
1500 generateDebugInfoIfNeeded(comp);
1503 comp->setNeedsClosures();
1506 Addr setCatchHandler = CodeGen::emitOp(comp, Op_PushExceptionHandler,
nullptr, OpValue::dummyAddr());
1507 comp->pushNest(finallyBlock ? CompileState::TryFinally : CompileState::OtherCleanup);
1509 tryBlock->generateExecCode(comp);
1511 CodeGen::emitOp(comp, Op_PopExceptionHandler);
1515 Addr jumpOverCatch = 0;
1517 jumpOverCatch = CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
1521 CodeGen::patchJumpToNext(comp, setCatchHandler, 0);
1523 Addr catchToFinallyEH = 0;
1530 catchToFinallyEH = CodeGen::emitOp(comp, Op_PushExceptionHandler,
nullptr, OpValue::dummyAddr());
1531 comp->pushNest(CompileState::TryFinally);
1537 OpValue catchVar = OpValue::immIdent(&exceptionIdent);
1538 CodeGen::emitOp(comp, Op_EnterCatch,
nullptr, &catchVar);
1539 comp->pushNest(CompileState::Scope);
1541 catchBlock->generateExecCode(comp);
1544 CodeGen::emitOp(comp, Op_ExitCatch);
1548 CodeGen::emitOp(comp, Op_PopExceptionHandler);
1553 CodeGen::patchJumpToNext(comp, jumpOverCatch, 0);
1558 CodeGen::patchJumpToNext(comp, catchToFinallyEH, 0);
1561 CodeGen::emitOp(comp, Op_DeferCompletion);
1562 comp->pushNest(CompileState::OtherCleanup);
1564 finallyBlock->generateExecCode(comp);
1566 OpValue otherTryFinally = OpValue::immBool(comp->inTryFinally());
1568 if (exitContextNeeded(comp)) {
1569 OpValue ourNode = OpValue::immNode(comp->functionBody());
1570 CodeGen::emitOp(comp, Op_ReactivateCompletionDebug,
nullptr, &otherTryFinally, &ourNode);
1572 CodeGen::emitOp(comp, Op_ReactivateCompletion,
nullptr, &otherTryFinally);
1578 void FunctionBodyNode::generateExecCode(CompileState *comp)
1581 OpValue scopeVal, scopeReg,
1582 globalVal, globalReg,
1585 comp->requestTemporary(OpType_value, &scopeVal, &scopeReg);
1586 comp->requestTemporary(OpType_value, &globalVal, &globalReg);
1587 comp->requestTemporary(OpType_value, &thisVal, &thisReg);
1589 CodeGen::emitOp(comp, Op_Preamble,
nullptr, &scopeReg, &globalReg, &thisReg);
1591 comp->setPreloadRegs(&scopeVal, &globalVal, &thisVal);
1593 OpValue evalResReg, evalResVal;
1594 if (comp->codeType() != FunctionCode) {
1595 comp->requestTemporary(OpType_value, &evalResVal, &evalResReg);
1596 comp->setEvalResultRegister(&evalResReg);
1600 if (comp->compileType() == Debug) {
1601 OpValue ourNode = OpValue::immNode(
this);
1602 CodeGen::emitOp(comp, Op_EnterDebugContext,
nullptr, &ourNode);
1607 Addr unwind = CodeGen::emitOp(comp, Op_PushExceptionHandler,
nullptr, OpValue::dummyAddr());
1610 BlockNode::generateExecCode(comp);
1613 if (comp->codeType() != FunctionCode) {
1614 CodeGen::emitOp(comp, Op_Return,
nullptr, &evalResVal);
1616 generateExitContextIfNeeded(comp);
1617 CodeGen::emitOp(comp, Op_Exit);
1621 CodeGen::patchJumpToNext(comp, unwind, 0);
1622 generateExitContextIfNeeded(comp);
1623 CodeGen::emitOp(comp, Op_PropagateException);
1626 void SwitchNode::generateExecCode(CompileState *comp)
1628 generateDebugInfoIfNeeded(comp);
1629 CaseBlockNode *caseBlock = this->block.get();
1635 comp->pushNest(CompileState::ContBreakTarget,
this);
1636 comp->pushDefaultBreak(
this);
1639 OpValue switchOn = expr->generateEvalCode(comp);
1641 WTF::Vector<Addr> list1jumps;
1642 WTF::Vector<Addr> list2jumps;
1646 for (ClauseListNode *iter = caseBlock->list1.get(); iter; iter = iter->next.get()) {
1647 OpValue
ref = iter->clause->expr->generateEvalCode(comp);
1649 CodeGen::emitOp(comp, Op_StrEq, &match, &switchOn, &ref);
1651 Addr jumpToClause = CodeGen::emitOp(comp, Op_IfJump,
nullptr, &match, OpValue::dummyAddr());
1652 list1jumps.append(jumpToClause);
1656 for (ClauseListNode *iter = caseBlock->list2.get(); iter; iter = iter->next.get()) {
1657 OpValue
ref = iter->clause->expr->generateEvalCode(comp);
1659 CodeGen::emitOp(comp, Op_StrEq, &match, &switchOn, &ref);
1661 Addr jumpToClause = CodeGen::emitOp(comp, Op_IfJump,
nullptr, &match, OpValue::dummyAddr());
1662 list2jumps.append(jumpToClause);
1666 defJump = CodeGen::emitOp(comp, Op_Jump,
nullptr, OpValue::dummyAddr());
1670 for (ClauseListNode *iter = caseBlock->list1.get(); iter; iter = iter->next.get()) {
1671 CodeGen::patchJumpToNext(comp, list1jumps[p], 1);
1672 if (iter->clause->source) {
1673 iter->clause->source->generateExecCode(comp);
1678 if (caseBlock->def) {
1679 CodeGen::patchJumpToNext(comp, defJump, 0);
1680 if (caseBlock->def->source) {
1681 caseBlock->def->source->generateExecCode(comp);
1686 for (ClauseListNode *iter = caseBlock->list2.get(); iter; iter = iter->next.get()) {
1687 CodeGen::patchJumpToNext(comp, list2jumps[p], 1);
1688 if (iter->clause->source) {
1689 iter->clause->source->generateExecCode(comp);
1695 if (!caseBlock->def) {
1696 CodeGen::patchJumpToNext(comp, defJump, 0);
1700 comp->popDefaultBreak();
1702 comp->resolvePendingBreaks(
this, CodeGen::nextPC(comp));
1705 void ImportStatement::generateExecCode(CompileState *)