Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
e08e79ec
Commit
e08e79ec
authored
Jul 30, 2014
by
Travis Hance
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removed rewriter1
parent
fc111bc5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
0 additions
and
617 deletions
+0
-617
src/asm_writing/rewriter.cpp
src/asm_writing/rewriter.cpp
+0
-467
src/asm_writing/rewriter.h
src/asm_writing/rewriter.h
+0
-146
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+0
-4
No files found.
src/asm_writing/rewriter.cpp
deleted
100644 → 0
View file @
fc111bc5
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "asm_writing/rewriter.h"
#include "asm_writing/assembler.h"
#include "asm_writing/icinfo.h"
#include "core/common.h"
#include "core/stats.h"
namespace
pyston
{
using
namespace
pyston
::
assembler
;
#define MAX_ARGS 16
Register
fromArgnum
(
int
argnum
)
{
switch
(
argnum
)
{
case
-
5
:
return
RBP
;
case
-
4
:
return
RSP
;
case
-
3
:
return
R11
;
case
-
2
:
return
R10
;
case
-
1
:
return
RAX
;
case
0
:
return
RDI
;
case
1
:
return
RSI
;
case
2
:
return
RDX
;
case
3
:
return
RCX
;
case
4
:
return
R8
;
case
5
:
return
R9
;
}
RELEASE_ASSERT
(
0
,
"%d"
,
argnum
);
}
RewriterVar
::
RewriterVar
(
Rewriter
*
rewriter
,
int
argnum
,
int
version
)
:
rewriter
(
rewriter
),
argnum
(
argnum
),
version
(
version
)
{
// assert(rewriter.icentry.get());
}
RewriterVar
&
RewriterVar
::
operator
=
(
const
RewriterVar
&
rhs
)
{
assert
(
rewriter
==
NULL
||
rewriter
==
rhs
.
rewriter
);
rhs
.
assertValid
();
rewriter
=
rhs
.
rewriter
;
argnum
=
rhs
.
argnum
;
version
=
rhs
.
version
;
return
*
this
;
}
#ifndef NDEBUG
void
RewriterVar
::
assertValid
()
const
{
assert
(
rewriter
);
rewriter
->
checkVersion
(
argnum
,
version
);
}
void
RewriterVar
::
lock
()
{
assertValid
();
rewriter
->
lock
(
argnum
);
}
void
RewriterVar
::
unlock
()
{
assertValid
();
rewriter
->
unlock
(
argnum
);
}
#endif
int
RewriterVar
::
getArgnum
()
{
// assert(rewriter);
return
argnum
;
}
RewriterVar
RewriterVar
::
getAttr
(
int
offset
,
int
dest
)
{
assertValid
();
rewriter
->
assembler
->
mov
(
Indirect
(
fromArgnum
(
this
->
argnum
),
offset
),
fromArgnum
(
dest
));
int
version
=
rewriter
->
mutate
(
dest
);
return
RewriterVar
(
rewriter
,
dest
,
version
);
}
void
RewriterVar
::
incAttr
(
int
offset
)
{
assertValid
();
rewriter
->
assembler
->
inc
(
Indirect
(
fromArgnum
(
this
->
argnum
),
offset
));
#ifndef NDEBUG
rewriter
->
changed_something
=
true
;
#endif
}
void
RewriterVar
::
setAttr
(
int
offset
,
const
RewriterVar
&
val
,
bool
user_visible
)
{
assertValid
();
val
.
assertValid
();
rewriter
->
assembler
->
mov
(
fromArgnum
(
val
.
argnum
),
Indirect
(
fromArgnum
(
this
->
argnum
),
offset
));
#ifndef NDEBUG
if
(
user_visible
)
rewriter
->
changed_something
=
true
;
#endif
}
RewriterVar
RewriterVar
::
move
(
int
dest_argnum
)
{
assertValid
();
int
version
;
if
(
dest_argnum
!=
this
->
argnum
)
{
assert
(
dest_argnum
<
6
);
if
(
this
->
argnum
>=
6
)
{
if
(
1
)
{
int
offset
=
(
this
->
argnum
-
6
)
*
8
+
rewriter
->
pushes
.
size
()
*
8
+
rewriter
->
alloca_bytes
;
rewriter
->
assembler
->
mov
(
Indirect
(
RSP
,
offset
),
fromArgnum
(
dest_argnum
));
}
else
{
int
stack_size
=
rewriter
->
rewrite
->
getFuncStackSize
();
ASSERT
(
stack_size
>
0
&&
stack_size
<
(
1
<<
30
),
"%d"
,
stack_size
);
int
offset
=
(
this
->
argnum
-
6
)
*
8
-
(
stack_size
-
8
);
rewriter
->
assembler
->
mov
(
Indirect
(
RBP
,
offset
),
fromArgnum
(
dest_argnum
));
}
}
else
{
rewriter
->
assembler
->
mov
(
fromArgnum
(
this
->
argnum
),
fromArgnum
(
dest_argnum
));
}
version
=
rewriter
->
mutate
(
dest_argnum
);
}
else
{
version
=
this
->
version
;
}
return
RewriterVar
(
rewriter
,
dest_argnum
,
version
);
}
void
RewriterVar
::
addGuard
(
intptr_t
val
)
{
assert
(
!
rewriter
->
changed_something
&&
"too late to add a guard!"
);
assertValid
();
rewriter
->
checkArgsValid
();
int
bytes
=
8
*
rewriter
->
pushes
.
size
()
+
rewriter
->
alloca_bytes
;
if
(
val
<
(
-
1L
<<
31
)
||
val
>=
(
1L
<<
31
)
-
1
)
{
rewriter
->
assembler
->
push
(
RBP
);
rewriter
->
assembler
->
mov
(
Immediate
(
val
),
RBP
);
rewriter
->
assembler
->
cmp
(
fromArgnum
(
this
->
argnum
),
RBP
);
rewriter
->
assembler
->
pop
(
RBP
);
}
else
{
rewriter
->
assembler
->
cmp
(
fromArgnum
(
this
->
argnum
),
Immediate
(
val
));
}
rewriter
->
assembler
->
jne
(
JumpDestination
::
fromStart
(
rewriter
->
rewrite
->
getSlotSize
()
-
bytes
/
8
));
}
void
RewriterVar
::
addAttrGuard
(
int
offset
,
intptr_t
val
)
{
assert
(
!
rewriter
->
changed_something
&&
"too late to add a guard!"
);
assertValid
();
rewriter
->
checkArgsValid
();
int
bytes
=
8
*
rewriter
->
pushes
.
size
()
+
rewriter
->
alloca_bytes
;
if
(
val
<
(
-
1L
<<
31
)
||
val
>=
(
1L
<<
31
)
-
1
)
{
rewriter
->
assembler
->
push
(
RBP
);
rewriter
->
assembler
->
mov
(
Immediate
(
val
),
RBP
);
rewriter
->
assembler
->
cmp
(
Indirect
(
fromArgnum
(
this
->
argnum
),
offset
),
RBP
);
rewriter
->
assembler
->
pop
(
RBP
);
}
else
{
rewriter
->
assembler
->
cmp
(
Indirect
(
fromArgnum
(
this
->
argnum
),
offset
),
Immediate
(
val
));
}
rewriter
->
assembler
->
jne
(
JumpDestination
::
fromStart
(
rewriter
->
rewrite
->
getSlotSize
()
-
bytes
/
8
));
}
void
RewriterVar
::
addGuardNotEq
(
intptr_t
val
)
{
assert
(
!
rewriter
->
changed_something
&&
"too late to add a guard!"
);
assertValid
();
rewriter
->
checkArgsValid
();
int
bytes
=
8
*
rewriter
->
pushes
.
size
()
+
rewriter
->
alloca_bytes
;
rewriter
->
assembler
->
cmp
(
fromArgnum
(
this
->
argnum
),
Immediate
(
val
));
rewriter
->
assembler
->
je
(
JumpDestination
::
fromStart
(
rewriter
->
rewrite
->
getSlotSize
()
-
bytes
/
8
));
}
bool
RewriterVar
::
isInReg
()
{
int
num_arg_regs
=
6
;
return
argnum
<
num_arg_regs
;
}
void
RewriterVar
::
push
()
{
assertValid
();
assert
(
isInReg
());
rewriter
->
assembler
->
push
(
fromArgnum
(
this
->
argnum
));
rewriter
->
addPush
(
this
->
version
);
}
RewriterVar
RewriterVar
::
cmp
(
AST_TYPE
::
AST_TYPE
cmp_type
,
const
RewriterVar
&
val
,
int
dest
)
{
assertValid
();
rewriter
->
assembler
->
cmp
(
fromArgnum
(
this
->
argnum
),
fromArgnum
(
val
.
argnum
));
switch
(
cmp_type
)
{
case
AST_TYPE
:
:
Eq
:
rewriter
->
assembler
->
sete
(
fromArgnum
(
dest
));
break
;
case
AST_TYPE
:
:
NotEq
:
rewriter
->
assembler
->
setne
(
fromArgnum
(
dest
));
break
;
default:
RELEASE_ASSERT
(
0
,
"%d"
,
cmp_type
);
}
int
version
=
rewriter
->
mutate
(
dest
);
return
RewriterVar
(
rewriter
,
dest
,
version
);
}
RewriterVar
RewriterVar
::
toBool
(
int
dest
)
{
assertValid
();
rewriter
->
assembler
->
test
(
fromArgnum
(
this
->
argnum
),
fromArgnum
(
this
->
argnum
));
rewriter
->
assembler
->
setnz
(
fromArgnum
(
dest
));
int
version
=
rewriter
->
mutate
(
dest
);
return
RewriterVar
(
rewriter
,
dest
,
version
);
}
RewriterVar
RewriterVar
::
add
(
int64_t
amount
)
{
assertValid
();
if
(
amount
>
0
)
rewriter
->
assembler
->
add
(
assembler
::
Immediate
(
amount
),
fromArgnum
(
this
->
argnum
));
else
rewriter
->
assembler
->
sub
(
assembler
::
Immediate
(
-
amount
),
fromArgnum
(
this
->
argnum
));
int
new_version
=
rewriter
->
mutate
(
this
->
argnum
);
return
RewriterVar
(
rewriter
,
this
->
argnum
,
new_version
);
}
Rewriter
*
Rewriter
::
createRewriter
(
void
*
ic_rtn_addr
,
int
num_orig_args
,
int
num_temp_regs
,
const
char
*
debug_name
)
{
assert
(
num_temp_regs
<=
2
&&
"unsupported"
);
static
StatCounter
rewriter_nopatch
(
"rewriter_nopatch"
);
ICInfo
*
ic
=
getICInfo
(
ic_rtn_addr
);
if
(
ic
==
NULL
)
{
rewriter_nopatch
.
log
();
return
NULL
;
}
assert
(
ic
->
getCallingConvention
()
==
llvm
::
CallingConv
::
C
&&
"Rewriter[1] only supports the C calling convention!"
);
return
new
Rewriter
(
ic
->
startRewrite
(
debug_name
),
num_orig_args
,
num_temp_regs
);
}
Rewriter
::
Rewriter
(
ICSlotRewrite
*
rewrite
,
int
num_orig_args
,
int
num_temp_regs
)
:
rewrite
(
rewrite
),
assembler
(
rewrite
->
getAssembler
()),
num_orig_args
(
num_orig_args
),
num_temp_regs
(
num_temp_regs
),
alloca_bytes
(
0
),
max_pushes
(
0
)
#ifndef NDEBUG
,
next_version
(
2
),
changed_something
(
false
)
#endif
,
ndecisions
(
0
),
decision_path
(
1
)
{
// printf("trapping here\n");
// assembler->trap();
// for (int i = 0; i < num_temp_regs; i++) {
// icentry->push(-2 - i);
//}
#ifndef NDEBUG
for
(
int
i
=
-
5
;
i
<
MAX_ARGS
;
i
++
)
{
versions
[
i
]
=
next_version
++
;
}
#endif
}
void
Rewriter
::
addPush
(
int
version
)
{
pushes
.
push_back
(
version
);
max_pushes
=
std
::
max
(
max_pushes
,
(
int
)
pushes
.
size
());
}
RewriterVar
Rewriter
::
alloca_
(
int
bytes
,
int
dest_argnum
)
{
// TODO should check to make sure we aren't crossing push+pops and allocas
// printf("alloca()ing %d bytes\n", bytes);
assert
(
bytes
%
sizeof
(
void
*
)
==
0
);
alloca_bytes
+=
bytes
;
assembler
->
sub
(
Immediate
(
bytes
),
RSP
);
assembler
->
mov
(
RSP
,
fromArgnum
(
dest_argnum
));
int
version
=
mutate
(
dest_argnum
);
return
RewriterVar
(
this
,
dest_argnum
,
version
);
}
RewriterVar
Rewriter
::
getArg
(
int
argnum
)
{
assert
(
argnum
>=
-
1
);
assert
(
argnum
<
MAX_ARGS
);
#ifndef NDEBUG
int
version
=
versions
[
argnum
];
assert
(
version
);
assert
(
version
==
argnum
+
7
);
#else
int
version
=
0
;
#endif
return
RewriterVar
(
this
,
argnum
,
version
);
}
RewriterVar
Rewriter
::
getRsp
()
{
int
argnum
=
-
4
;
#ifndef NDEBUG
int
version
=
versions
[
argnum
];
#else
int
version
=
0
;
#endif
assert
(
version
);
return
RewriterVar
(
this
,
argnum
,
version
);
}
RewriterVar
Rewriter
::
getRbp
()
{
int
argnum
=
-
5
;
#ifndef NDEBUG
int
version
=
versions
[
argnum
];
#else
int
version
=
0
;
#endif
assert
(
version
);
return
RewriterVar
(
this
,
argnum
,
version
);
}
#ifndef NDEBUG
void
Rewriter
::
checkArgsValid
()
{
for
(
int
i
=
0
;
i
<
num_orig_args
;
i
++
)
checkVersion
(
i
,
i
+
7
);
}
int
Rewriter
::
mutate
(
int
argnum
)
{
ASSERT
(
locked
.
count
(
argnum
)
==
0
,
"arg %d is locked!"
,
argnum
);
assert
(
versions
.
count
(
argnum
));
int
rtn_version
=
++
next_version
;
// printf("mutating %d to %d\n", argnum, rtn_version);
versions
[
argnum
]
=
rtn_version
;
return
rtn_version
;
}
void
Rewriter
::
lock
(
int
argnum
)
{
assert
(
locked
.
count
(
argnum
)
==
0
);
locked
.
insert
(
argnum
);
}
void
Rewriter
::
unlock
(
int
argnum
)
{
assert
(
locked
.
count
(
argnum
)
==
1
);
locked
.
erase
(
argnum
);
}
void
Rewriter
::
checkVersion
(
int
argnum
,
int
version
)
{
assert
(
version
>
0
);
ASSERT
(
version
==
versions
[
argnum
],
"arg %d got updated from %d to %d"
,
argnum
,
version
,
versions
[
argnum
]);
}
#endif
void
Rewriter
::
trap
()
{
assembler
->
trap
();
}
void
Rewriter
::
nop
()
{
assembler
->
nop
();
}
void
Rewriter
::
annotate
(
int
num
)
{
assembler
->
emitAnnotation
(
num
);
}
RewriterVar
Rewriter
::
loadConst
(
int
argnum
,
intptr_t
val
)
{
assembler
->
mov
(
Immediate
(
val
),
fromArgnum
(
argnum
));
int
version
=
mutate
(
argnum
);
return
RewriterVar
(
this
,
argnum
,
version
);
}
RewriterVar
Rewriter
::
call
(
void
*
func_addr
)
{
#ifndef NDEBUG
changed_something
=
true
;
#endif
// printf("%ld pushes, %d alloca bytes\n", pushes.size(), alloca_bytes);
int
bytes
=
8
*
pushes
.
size
()
+
alloca_bytes
;
bool
didpush
;
if
(
bytes
%
16
==
8
)
{
assembler
->
push
(
RDI
);
didpush
=
true
;
}
else
{
assert
(
bytes
%
16
==
0
);
didpush
=
false
;
}
assembler
->
emitCall
(
func_addr
,
R11
);
if
(
didpush
)
assembler
->
pop
(
RDI
);
#ifndef NDEBUG
int
num_arg_regs
=
6
;
for
(
int
i
=
-
3
;
i
<
num_arg_regs
;
i
++
)
{
mutate
(
i
);
}
#endif
return
RewriterVar
(
this
,
-
1
,
mutate
(
-
1
));
}
RewriterVar
Rewriter
::
pop
(
int
argnum
)
{
assert
(
pushes
.
size
()
>
0
);
int
version
=
pushes
.
back
();
pushes
.
pop_back
();
#ifndef NDEBUG
versions
[
argnum
]
=
version
;
#endif
// printf("popping %d to %d\n", version, argnum);
assembler
->
pop
(
fromArgnum
(
argnum
));
return
RewriterVar
(
this
,
argnum
,
version
);
}
void
Rewriter
::
addDecision
(
int
way
)
{
assert
(
ndecisions
<
60
);
ndecisions
++
;
decision_path
=
(
decision_path
<<
1
)
|
way
;
}
void
Rewriter
::
addDependenceOn
(
ICInvalidator
&
invalidator
)
{
rewrite
->
addDependenceOn
(
invalidator
);
}
void
Rewriter
::
commit
()
{
static
StatCounter
rewriter_commits
(
"rewriter_commits"
);
rewriter_commits
.
log
();
// make sure we left the stack the way we found it:
assert
(
pushes
.
size
()
==
0
);
assert
(
alloca_bytes
==
0
);
rewrite
->
commit
(
decision_path
,
this
);
}
void
Rewriter
::
finishAssembly
(
int
continue_offset
)
{
assembler
->
jmp
(
JumpDestination
::
fromStart
(
continue_offset
));
assembler
->
fillWithNopsExcept
(
max_pushes
);
for
(
int
i
=
0
;
i
<
max_pushes
;
i
++
)
{
assembler
->
pop
(
RAX
);
}
}
}
src/asm_writing/rewriter.h
deleted
100644 → 0
View file @
fc111bc5
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_ASMWRITING_REWRITER_H
#define PYSTON_ASMWRITING_REWRITER_H
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include "asm_writing/icinfo.h"
#include "core/ast.h"
namespace
pyston
{
class
ICInfo
;
class
ICSlotInfo
;
class
ICInvalidator
;
class
Rewriter
;
namespace
assembler
{
class
Assembler
;
}
// TODO Maybe should make these classes abstract and then pick between a debug implementation
// and a release one, instead of trying to make one class do both?
class
RewriterVar
{
private:
Rewriter
*
rewriter
;
int
argnum
;
int
version
;
public:
RewriterVar
()
:
rewriter
(
NULL
),
argnum
(
-
100
),
version
(
-
100
)
{}
RewriterVar
(
Rewriter
*
rewriter
,
int
argnum
,
int
version
);
RewriterVar
&
operator
=
(
const
RewriterVar
&
rhs
);
#ifndef NDEBUG
void
assertValid
()
const
;
void
lock
();
void
unlock
();
#else
inline
void
assertValid
()
const
{}
inline
void
lock
()
{}
inline
void
unlock
()
{}
#endif
int
getArgnum
();
void
addGuard
(
intptr_t
val
);
void
addGuardNotEq
(
intptr_t
val
);
// More efficient than getAttr().addGuard(), but less efficient than addGuard() if the value is already available:
void
addAttrGuard
(
int
offset
,
intptr_t
val
);
RewriterVar
getAttr
(
int
offset
,
int
dest
);
void
incAttr
(
int
offset
);
void
setAttr
(
int
offset
,
const
RewriterVar
&
val
,
bool
user_visible
=
true
);
RewriterVar
move
(
int
argnum
);
bool
isInReg
();
void
push
();
RewriterVar
cmp
(
AST_TYPE
::
AST_TYPE
cmp_type
,
const
RewriterVar
&
val
,
int
dest
);
RewriterVar
toBool
(
int
dest
);
RewriterVar
add
(
int64_t
amount
);
friend
class
Rewriter
;
};
class
Rewriter
:
public
ICSlotRewrite
::
CommitHook
{
private:
std
::
unique_ptr
<
ICSlotRewrite
>
rewrite
;
assembler
::
Assembler
*
assembler
;
const
int
num_orig_args
;
const
int
num_temp_regs
;
void
finishAssembly
(
int
continue_offset
);
int
alloca_bytes
;
int
max_pushes
;
std
::
vector
<
int
>
pushes
;
#ifndef NDEBUG
std
::
unordered_map
<
int
,
int
>
versions
;
int
next_version
;
bool
changed_something
;
std
::
unordered_set
<
int
>
locked
;
#endif
int
ndecisions
;
uint64_t
decision_path
;
Rewriter
(
ICSlotRewrite
*
rewrite
,
int
num_orig_args
,
int
num_temp_regs
);
void
addPush
(
int
version
);
public:
static
Rewriter
*
createRewriter
(
void
*
ic_rtn_addr
,
int
num_orig_args
,
int
num_temp_regs
,
const
char
*
debug_name
);
#ifndef NDEBUG
int
mutate
(
int
argnum
);
void
lock
(
int
argnum
);
void
unlock
(
int
argnum
);
void
checkVersion
(
int
argnum
,
int
version
);
void
checkArgsValid
();
#else
inline
int
mutate
(
int
argnum
)
{
return
0
;
}
inline
void
lock
(
int
argnum
)
{}
inline
void
unlock
(
int
argnum
)
{}
inline
void
checkVersion
(
int
argnum
,
int
version
)
{}
inline
void
checkArgsValid
()
{}
#endif
int
getFuncStackSize
()
{
return
rewrite
->
getFuncStackSize
();
}
int
getScratchRbpOffset
()
{
return
rewrite
->
getScratchRbpOffset
();
}
int
getScratchBytes
()
{
return
rewrite
->
getScratchBytes
();
}
RewriterVar
getRbp
();
RewriterVar
getRsp
();
void
addDecision
(
int
way
);
RewriterVar
alloca_
(
int
bytes
,
int
dest_argnum
);
RewriterVar
getArg
(
int
argnum
);
void
trap
();
void
nop
();
void
annotate
(
int
num
);
RewriterVar
pop
(
int
argnum
);
RewriterVar
call
(
void
*
func_addr
);
RewriterVar
loadConst
(
int
argnum
,
intptr_t
val
);
void
addDependenceOn
(
ICInvalidator
&
);
void
commit
();
friend
class
RewriterVar
;
};
}
#endif
src/runtime/objmodel.cpp
View file @
e08e79ec
...
...
@@ -25,7 +25,6 @@
#include "llvm/Support/Path.h"
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "asm_writing/rewriter2.h"
#include "codegen/compvars.h"
#include "codegen/irgen/hooks.h"
...
...
@@ -609,9 +608,6 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs2* rewrit
}
#endif
RewriterVar
r_new_array
;
RewriterVarUsage2
r_new_array2
(
RewriterVarUsage2
::
empty
());
int
new_size
=
sizeof
(
HCAttrs
::
AttrList
)
+
sizeof
(
Box
*
)
*
(
numattrs
+
1
);
if
(
numattrs
==
0
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment